{"id":6223,"date":"2024-04-25T14:22:55","date_gmt":"2024-04-25T14:22:55","guid":{"rendered":"https:\/\/www.solutionstreet.com\/blog\/?p=6223"},"modified":"2024-04-25T15:10:48","modified_gmt":"2024-04-25T15:10:48","slug":"flutterflow-tutorial-part-2","status":"publish","type":"post","link":"https:\/\/www.solutionstreet.com\/blog\/2024\/04\/25\/flutterflow-tutorial-part-2\/","title":{"rendered":"FlutterFlow Tutorial &#8211; Part 2"},"content":{"rendered":"<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1022\" height=\"429\" src=\"https:\/\/www.solutionstreet.com\/blog\/wp-content\/uploads\/2024\/04\/mobilephone3-Copytitle2.png\" alt=\"\" class=\"wp-image-6275\" style=\"width:712px;height:auto\" srcset=\"https:\/\/www.solutionstreet.com\/blog\/wp-content\/uploads\/2024\/04\/mobilephone3-Copytitle2.png 1022w, https:\/\/www.solutionstreet.com\/blog\/wp-content\/uploads\/2024\/04\/mobilephone3-Copytitle2-300x126.png 300w, https:\/\/www.solutionstreet.com\/blog\/wp-content\/uploads\/2024\/04\/mobilephone3-Copytitle2-768x322.png 768w\" sizes=\"auto, (max-width: 1022px) 100vw, 1022px\" \/><\/figure>\n<\/div>\n\n\n<h1 class=\"wp-block-heading\">Introduction<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">This is Part 2 (of 2) of my <a href=\"https:\/\/flutterflow.io\/\" target=\"blank\" rel=\"noopener\">FlutterFlow<\/a> tutorial. FlutterFlow is a no-code\/low-code browser-based builder for developing native mobile applications. In <a href=\"https:\/\/www.solutionstreet.com\/blog\/2024\/03\/26\/flutterflow-tutorial-part-1\/\" target=\"blank\" rel=\"noopener\">Part 1<\/a>, I introduced FlutterFlow and created a mobile app with the basics of authentication using Sign Up\/Sign In page templates with a database connection to a <a href=\"https:\/\/supabase.com\/\" target=\"blank\" rel=\"noopener\">Supabase<\/a> database. In this final part, I will create some mobile pages to display basic <a href=\"https:\/\/en.wikipedia.org\/wiki\/Create,_read,_update_and_delete\" target=\"blank\" rel=\"noopener\">CRUD<\/a> processing and then review the overall pros and cons of FlutterFlow.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Tutorial (continued)<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">To pick up where we left off, we have a blank home page which just has the title of \u201cPage Title\u201d and a logout icon button. Let\u2019s swap to Supabase and create a new database table containing a list of pickleball players. Let\u2019s assume the app we are creating will contain a list of these players with their <a href=\"https:\/\/usapickleball.org\/tournaments\/tournament-player-ratings\/player-skill-rating-definitions\/\" target=\"blank\" rel=\"noopener\">skill rating<\/a> (this is a number from 1.0 to 5.5). Although we won\u2019t build out the full mobile application you can see how this player listing could be used to schedule games with calendaring functionality or just pair up players for tournaments. For now, let\u2019s just create the players table with mobile UI screens that allows the user to view, edit, delete, and create the players.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Database Table Creation<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/XSbSKFz75yeFSqOY-sVLfkJZyS8qrr5Gcd_PH47X9HLPBGv5mELpUVF5VN02leGa2ti4JF8fWWFuPFMjwyv05n0iqKvgRptwJFgdRrcqHzonf9IWTouNlXxnieaKEphS6Y1qvwYVxlAj4x9koAw4ih0\" width=\"156\" height=\"148\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Within Supabase once you are within your DemoDB project, which we created in Part 1 of the tutorial, select the Table Editor menu icon on the left and create a \u201cplayers\u201d table that contains a <em>first_name<\/em>, <em>last_name<\/em>, and <em>skill_rating<\/em>. Add columns to the table at the bottom of the table creation screen. We will also add a <em>user_id<\/em> field to associate the players record to the user such that every user of the mobile app will have their own list of players. By default, Supabase adds an <em>id<\/em> field and a <em>created_at<\/em> timestamp.&nbsp;<\/p>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\"><img loading=\"lazy\" decoding=\"async\" width=\"372\" height=\"260\" src=\"https:\/\/lh7-us.googleusercontent.com\/qcKJSxhmT_lKGJMfdfKrOTE1kf-bHk8OfDsOP46jrHqcq_Rs3L_M1ETa83vRUo03sAb-Io0-pJ1rWW_z3BuqWMYVzDO4arp9Msui2DUNzjKZgQQ77go7EzFe3osIpr61SD9IQ0fefTuyTvRr2PUUZI0\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Also uncheck the \u201cIs Nullable\u201d toggle via the settings icon for the fields you created.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter is-resized\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/IcYj0L6_3cOTOw7OPvsuCo2Zk_y6bbCw6JMLwXfFaW4JJKebEPv6h9eXq4PVGNK_Y2MtnuovNSUL0VdMiZaCHvpKAxcaHPDIYMT1G0Q7HY8w8HQEmeY3amI06EDs_QnXOGFt4z7e4lGyR7YkMoZ15gQ\" alt=\"\" style=\"width:539px;height:auto\"\/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">Once you have created the table, you should see the \u201cplayers\u201d table listed in the Table Editor section of Supabase. There you will click on the three dots and select \u201cView Policies.\u201d We need to establish a <a href=\"https:\/\/supabase.com\/docs\/guides\/database\/postgres\/row-level-security\" target=\"blank\" rel=\"noopener\">row level policy<\/a> for access to this table. Here we will only allow the current user the ability to access their own data. Select the \u201cCreate New Policy\u201d button and create a policy where we use the following statement as part of the check:&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">((auth.jwt() -&gt;&gt; &#8216;sub&#8217;::text) = user_id)<\/p>\n\n\n\n<div class=\"wp-block-media-text has-media-on-the-right is-stacked-on-mobile is-vertically-aligned-top\"><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\">This statement is ensuring that the user that\u2019s part of the auth token sent to Supabase is the same as the user_id field. Give this policy a name: \u201cAllow access to players based on user_id,\u201d select the \u201cAll\u201d radio button (since we want this policy to apply to all actions), select the \u201c<a href=\"https:\/\/supabase.com\/docs\/guides\/database\/postgres\/row-level-security#insert-policies\" target=\"blank\" rel=\"noopener\">Use check expression<\/a>\u201d (since we want this policy to apply to new rows), and add the above&nbsp; statement twice in the policy. Save the policy and we are all set for now with Supabase (verify your work against this screenshot).<\/p>\n<\/div><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/VBAGIf1hzCf_PFjB6gEzLER8mJeisFvWBtwjmkEH_tz6pYZkrORbC6j3Str7HqLA-UFJd8EbZ-cVk_5hOBMlr8d5ulyuNjpq7Bggq9W-S5tXPw62C1uVh7Zp0Joo44t0PDBOsZx5W8QUfzru6SuZyDg\" alt=\"\"\/><\/figure><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Return to your FlutterFlow project and under Settings\/Supabase, click the \u201cGet Schema\u201d button and you should see your \u201cplayers\u201d table fully populate in the IDE. At this point your mobile app has access to reference those fields. You can think of this as the UI database model.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Reading<\/strong> players<\/h2>\n\n\n\n<div class=\"wp-block-media-text has-media-on-the-right is-stacked-on-mobile is-vertically-aligned-top\" style=\"grid-template-columns:auto 38%\"><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\">Let\u2019s change the \u201cHome Page\u201d to display our player records. From the Column widget, add a Container widget child. Then set the height and width of the container to 100%.<\/p>\n<\/div><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/QwkrAReA2oj0bBrAXGu65d5BocoUnxAo8GASCplNoClhj67VD4AJ-hUy5XRpYraRFjp6MdU2Sq8zNcpyACyT6lHl10nONWn48fny4R_zryVGP1tfp3IOJEinLQEJuAQFovTAl2ur5hTkobBm-gfqScc\" alt=\"\"\/><\/figure><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<div class=\"wp-block-media-text has-media-on-the-right is-stacked-on-mobile\" style=\"grid-template-columns:auto 38%\"><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\"><\/p>\n<\/div><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/aWD16vgyqXD22fe4kJIjSh85GMlDNwbTm6tIlBXUl0GsE0BWeV7UPdFBuTfXqOqFp3aW8JHMRqoXEbpV69KfWvwJAL_ygHG1nd76gsmqOCw3E_-wVqUJY7bD3tIgIa34Amm4p9lqLnY2IFRvNb3jekM\" alt=\"\"\/><\/figure><\/div>\n\n\n\n<div class=\"wp-block-media-text has-media-on-the-right is-stacked-on-mobile\" style=\"grid-template-columns:auto 38%\"><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\">From the Container widget, add a ListView widget child. Here we are going to have FlutterFlow retrieve all of the player records associated with the logged in user. On the right side of the IDE (while in the context of the ListView) we are going to add a query.<\/p>\n<\/div><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/9geyEgvX9Rhu4UaRAVOqEZpg9LWqR2fnUvoL1l6q_oj0ViWdhoAVzU8gHIOIVgdVH3IzjOBd6b598xe6jF4KjiiAkFWN2Q69Y3QvPZM5G0sfPQu5dCsVkWOwdrO_BDn1KsACcaVDhRdmLti0Ne8m4yo\" alt=\"\"\/><\/figure><\/div>\n\n\n\n<div class=\"wp-block-media-text has-media-on-the-right is-stacked-on-mobile\" style=\"grid-template-columns:auto 38%\"><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\">Add the initial fields selecting \u201cSupabase Query\u201d and \u201cplayers\u201d table.<\/p>\n<\/div><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/5CgmZARPkkufT6SaqXE1NRjkHe5EnEOVCr3HdYMCH3ryuggde71Nv4FdOH7p3E3i8CsIWQRY30hgfk-wgQTK0XQxFGKLuTIAr_geervBtP2GYFcqaPBXvviMFjiUZZCMhkzW_YmK8RLWEKaRBSdgirE\" alt=\"\"\/><\/figure><\/div>\n\n\n\n<div class=\"wp-block-media-text is-stacked-on-mobile\" style=\"grid-template-columns:39% auto\"><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/bk6N5SwWVx7112VsDsMOsqJDkvXDYjO6m1UrY7dRtfxRu8LycldmEFvBKCrue79Gs_eHhGQmljBDkXkcEfhbev45ItbySBJDWdeuLQKlRzQrPNdAGt5QNpv76LTMWcHmZdtX5okPi2syturH8gjt6o4\" alt=\"\"\/><\/figure><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\">And continue to add the filter (Add Filter button) and set the appropriate values where the user_id of the table record must equal the User ID of the authenticated user.<\/p>\n<\/div><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<div class=\"wp-block-media-text is-stacked-on-mobile\" style=\"grid-template-columns:39% auto\"><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/VRbv387jE2zK_zadycgpcPSH__-ISJwZ-pPA52HcPJtK6emnh3UtPaoidYT2DFR-ZG8C268KxhHuiV81MkaT8KY1rHa0ckUqY07rjx6cy5l3qup4lzAGqIUkJhsdExxLC_3uTZ6085jutZ7ODz0UHbM\" alt=\"\"\/><\/figure><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\">Also establish ordering by ordering the list via the created_at timestamp in descending order (i.e., last inserted at the top of the list).<\/p>\n<\/div><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<div class=\"wp-block-media-text is-stacked-on-mobile\" style=\"grid-template-columns:39% auto\"><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/VzzH7HHsosBSYEn1Kj9JOiUyriv-0-Vik8904gtF8VDJUvDpsyFo7AJcBOcnFHo1He_wv0eMVDaClw82HA4eDuf2nJjungHdT7UU03sDcul7EtrKLcXG9vYWe-qsLjr9_-Vo3Ns5O7-ggCF2kQXE1Ac\" alt=\"\"\/><\/figure><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\">Confirm the query creation and you should see this.<\/p>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-media-text has-media-on-the-right is-stacked-on-mobile\" style=\"grid-template-columns:auto 49%\"><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\">Now we need to add a ListTile widget as a child of the ListView to display our data. In the properties of the ListTile we will add the first_name and last_name as a combination text for the title of the ListTile and the skill_rating as the subtitle. First select the combination text.<\/p>\n<\/div><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/E3iXZ4ow-tys4B2jmjCbiyTkVq0nBUutKcwqNswqB9sTTwBnN94o-uY2nksMmuBRl-pZVWBO5JMcrv_uLMDjJ4Md6m34_-lgMUjUtZm2JdOGByRPbb86Cq_qJ0eKHZFLBJ5NGWsBZVGRhkU_Mo6WvTw\" alt=\"\"\/><\/figure><\/div>\n\n\n\n<div class=\"wp-block-media-text has-media-on-the-right is-stacked-on-mobile\" style=\"grid-template-columns:auto 34%\"><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\">You will select the first_name and last_name from the \u201cPlayers Row\u201d and add a space between the two fields.<\/p>\n<\/div><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/NY83_UGQwCwWbCEN21-dBZ3VLGV7c6QtMY3rCmH1H2BxO35l7HQmh0n3MT7m--_7UknAWMu30vmcfrXksBaAzsvrImhFu5QrmPaKUxgTiJdEMGGWCWOfFsstOCYScIEr5XdBvUQ2qR0_ByADBRwW1U4\" alt=\"\"\/><\/figure><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">For the Subtitle we will do something similar by displaying the skill_rating with the text of \u201cRating: \u201c just prior to the field.<\/p>\n\n\n\n<div class=\"wp-block-media-text has-media-on-the-right is-stacked-on-mobile\" style=\"grid-template-columns:auto 34%\"><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\">Now we can test out our page, but first we need some data. Let\u2019s manually add some data to Supabase. Go back to Supabase and select the Authentication page. There you will see the user(s) you created previously when signing up for an account. Copy the UUID from the user you wish to test. Go to the Table Editor and select \u201cplayers\u201d and insert select rows of data by only entering the first_name, last_name, skill_rating, and user_id (where the UUID you copied is pasted here). Now that you have a few rows of data, test your app via <a href=\"https:\/\/docs.flutterflow.io\/deploying-your-app\/testing-your-app\" target=\"blank\" rel=\"noopener\">Test Mode<\/a> (selecting the lightning bolt). You should see something like this with your own data.<\/p>\n<\/div><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/xhGm_nqPKhw_AmbvbBM0x-n0YyPFxeE5d728qxdwAfpvdtNBuMBQcnnUGVROBHytQvY6SXPxFxCc0rGmnL_s568MvL5uCAk8rZQjp6ik2JkroVs3eDx7rEAFh5kFgLzzyEiQ0dhZ3HeGYFr2QugZL3Q\" alt=\"\"\/><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Deleting<\/strong> players<\/h2>\n\n\n\n<div class=\"wp-block-media-text has-media-on-the-right is-stacked-on-mobile is-vertically-aligned-center\"><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\">Now that we have the list of players, let\u2019s clean up the Page Title and add create, update, and delete functionality. I\u2019ll move faster through the rest of the instructions since, by now, you should have a handle on the IDE and what\u2019s required. First, change the title of the Home Page to \u201cPickleball Players.\u201d Let\u2019s add the delete functionality first with a slidable widget. Select the ListTile widget and you will see a property called \u201cSlidable.\u201d Turn that on.<\/p>\n<\/div><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/ntRyIeUkgKPiMMc6pCBShbPgPd4ayjMBV7HHa2IjmYxAP707HprDjOtVgFfRlfcVyC2gqmSSx-a_9ZLr4ubSFolkV81xnKZmIWHgVnCUcMG3aMs3yNCwqjCm17wk0Hxy1v8RPa7fXAt1Wy8qSjwRaSw\" alt=\"\"\/><\/figure><\/div>\n\n\n\n<div class=\"wp-block-media-text has-media-on-the-right is-stacked-on-mobile\" style=\"grid-template-columns:auto 34%\"><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\">By default you will have a Share action so change that (the SlidableActionWidget that was just created) to a Delete action (change the icon, text, color).<\/p>\n<\/div><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/1ie-ZYR_-gcETn9h9ywi1fF93AsTIaBu-U3-XFA9auF68rz5LYNni927uQ3jl5QpmM-oTTNwA9WPSrqUKj2jsUlJo_CUJ9yJRqqUPkKoDM9xIN3mRraj5YbIuRfs1Ur4B1IeS3rhM9MDW-fNMzddoR4\" alt=\"\"\/><\/figure><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<div class=\"wp-block-media-text has-media-on-the-right is-stacked-on-mobile\" style=\"grid-template-columns:auto 34%\"><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\">With the Slidable Action Widget selected, open the Action Flow Editor and add these two actions. First we will add the call to Supabase to delete the row. Be sure to add a Filter (Matching Rows) where the id of the database row is equal to the id of the row in the UI.<\/p>\n<\/div><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/44cseFvGSdj6VEKH9XyO8eyWaN9unIlcMIL2n1YHMATPgLvRl6iJGRVcdbR5osGuRbvA7Ioqa_017ujKX3gicXvBWSj5mGbeQJ9lJwhTbztNfQZGGRNvZ3nwCds-CpMoXFQ9pViSXel85w_T4h116AY\" alt=\"\"\/><\/figure><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<div class=\"wp-block-media-text has-media-on-the-right is-stacked-on-mobile\" style=\"grid-template-columns:auto 34%\"><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\">Then add a \u201cRefresh Database Request\u201d action on the ListView widget to ensure that the mobile page is refreshed with data. You can now test the delete functionality by sliding the row in test mode to delete the row.<\/p>\n<\/div><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/AeaCz2Z5fizcq7hwSSlZr3o7L7L_UuSaXM_aWM2ti461vnCMsq4grQzMxeXo6PlmHtXu5RU8rbMHSJqwNMN1EXGIIRhH0HafU0VYMDYA6SOrkVi1CL_wWjb9Ah7p3qCEUtoBQgMKnk21zEZDYp3vlFM\" alt=\"\"\/><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Creating<\/strong> players<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Now we can add the Create Player functionality. Let\u2019s add a new page. We can do this in many ways including creating a blank page or copying the Home Page to start. I duplicated the Home Page, renamed the page to \u201cCreatePlayer,\u201d deleted the Container and added all of the necessary fields. Here is what my page looks like and also the widget structure. See if you can recreate what I did.<\/p>\n\n\n\n<div class=\"wp-block-media-text has-media-on-the-right is-stacked-on-mobile is-vertically-aligned-top\" style=\"grid-template-columns:auto 33%\"><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\">Several notes to help you:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Since I copied this page from the HomePage I already had the AppBar with one IconButton (exit\/logout). I simply added a second IconButton with a home image and set the action to Navigate to the HomePage.<\/li>\n\n\n\n<li>The First Name and Last Name fields are simply TextFields. Besides changing the label there is nothing else to do with those fields.&nbsp;<\/li>\n\n\n\n<li>For the DropDown, which represents the Skill Rating, be sure to select \u201cAdd Option Labels\u201d and set the \u201cOption Value Data Type\u201d to Double. Since the skill_rating is a Float in Supabase we need this to be set to a numeric type otherwise FlutterFlow won\u2019t allow us to use this Dropdown for the skill_rating column without some conversion code. Add dropdown values of 1.0 through 5.5 in 0.5 increments.<\/li>\n<\/ul>\n<\/div><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/uKpqAn-DtORcg07YzAysSojDlFpEj33EW7X8jLWLqGl0uXv6goFr5iSBE9L-QDxhgWO9HHmduxjexLvoHv1lwixcHcSApvMgzNbc89JuaXlga0EWDujZBk1ijqKRADTSJ3AU_8gIRHHpk195C2dzRNI\" alt=\"\"\/><\/figure><\/div>\n\n\n\n<div class=\"wp-block-media-text has-media-on-the-right is-stacked-on-mobile is-vertically-aligned-top\" style=\"grid-template-columns:auto 33%\"><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\"><\/p>\n<\/div><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/dQ0J27jk_8yBYux8rcMhywQeqG9N8h61EPtlfVy6KoMypVOjei34OdwTmxq7Isx-FFg28GoqoZ8h30qC3DbzB2AMkOm0HntidxppLSbnt-wDiVeplTv1kX9Jedi_9-aFmHzNlS6AHdGHhPuSNF6cuXw\" alt=\"\"\/><\/figure><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<div class=\"wp-block-media-text has-media-on-the-right is-stacked-on-mobile is-vertically-aligned-top\" style=\"grid-template-columns:auto 33%\"><div class=\"wp-block-media-text__content\">\n<ul class=\"wp-block-list\">\n<li>Lastly, I have the action flow as follows for the Create button. I first validate the form (you can add some validation to the form on your own). Then I create the insert call to Supabase. Be sure to set the three fields from the form and the user_id. This is done by selecting the <a href=\"https:\/\/docs.flutterflow.io\/data-and-backend\/state-management\" target=\"blank\" rel=\"noopener\">Widget State<\/a> of the data. Then I call \u201cShow Snack Bar\u201d with a message that the record was inserted (this is a popup banner in the footer of the mobile device). Finally I reset the form fields &#8211; in two parts since text fields and dropdowns are handled separately.&nbsp;<\/li>\n<\/ul>\n<\/div><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/PH-WO9LrDYdeZ0D9U-DzBcz_XFC1mTOROiumZaBgOaMR8s-QZwySyoLjskBAsha7rdQFrKcPZr1N91jOqHlHIOO_7h4XXj_LKw9KYPDB_UN3G0Njwp9E8RoYeZi0X-LmL1ldSE3_xdV8DaABN5Ry3Ik\" alt=\"\"\/><\/figure><\/div>\n\n\n\n<div class=\"wp-block-media-text is-stacked-on-mobile\" style=\"grid-template-columns:47% auto\"><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/V6fj6-DZAeWaIDCWiG3AQzVPSwBW_VshRd7x9ibJekhHEHX7TgQC1S8AvvNe34N8dEus4251U9AlVCgwg7gpqp-uMaPLZlTuNAWFcXJPSH3AbxnUQnMImefDQeieLk1-vNnWtEl9SPfrisHDno4ksls\" alt=\"\"\/><\/figure><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\">We then go back to the HomePage and add an IconButton to handle navigating to the new page. Here I simply created the IconButton with an add-style image and set the Action to navigate to CreatePlayer. Sometimes it\u2019s hard to get the formatting\/justification of the widgets working properly, but play around with the various properties. Now you can test creating new players.&nbsp;<\/p>\n<\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Updating<\/strong> players<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Finally, let\u2019s add the update portion. Simply duplicate the CreatePlayer page and call the new page UpdatePlayer. Let\u2019s make the following adjustments:<\/p>\n\n\n\n<div class=\"wp-block-media-text has-media-on-the-right is-stacked-on-mobile is-vertically-aligned-top\" style=\"grid-template-columns:auto 32%\"><div class=\"wp-block-media-text__content\">\n<ul class=\"wp-block-list\">\n<li>While selecting the page-level widget (UpdatePlayer) you will see the ability to add Page Parameters on the right. Create a new parameter called currentPlayer and set it to a Supabase row (players). This parameter will be set from the HomePage when selecting a player row.<\/li>\n<\/ul>\n<\/div><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/B_UmUOMlvhIbyoYJcLTVIUwiP4BcdVxJtXNZfthKzIJvUfwi3pkDddCjF8EvIFPIgGMumKXA-aQmr3ddqI9ZzkzNqLKyQ_tssCzmxau02xwlukJEUMVkFoH2ALbNUd6EAh7VQWQOTrZgORi0trx0FCc\" alt=\"\"\/><\/figure><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>In the AppBar change the title text of the page to \u201cUpdate Player.\u201d<\/li>\n\n\n\n<li>Select the three fields individually and set the \u201cInitial Value\u201d of the respective fields to the associated field from page parameter. This is just loading up the field values from the current player record.<\/li>\n\n\n\n<li>Change the \u201cCreate\u201d button text to \u201cUpdate.\u201d<\/li>\n<\/ul>\n\n\n\n<div class=\"wp-block-media-text has-media-on-the-right is-stacked-on-mobile is-vertically-aligned-top\" style=\"grid-template-columns:auto 33%\"><div class=\"wp-block-media-text__content\">\n<ul class=\"wp-block-list\">\n<li>In the Action Flow for the Update, change the 2nd action Backend Call to be an Update rather than an Insert. Also, add a filter (Matching Rows) since within a database update we need a WHERE clause and setting the id to be equal to the id of the currentPlayer is all we need.<\/li>\n<\/ul>\n<\/div><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/D9ULDQpFLZj7oBbl4yCXFVuDaZQDc9jDzo_nto1h7Zfes0S_9Z1k6ciiI2qbJ0VPhpWynSL1xO_H0Styvwmb99dJtbzu7Zet9oZ816seZlB8W47gNqMmyWHWksfkvvIGYQoqh0ql4ifEEx2upU_DMgQ\" alt=\"\"\/><\/figure><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Also, in the Action Flow Editor, remove the two \u201cReset Form Fields\u201d actions (via the three dots). Since we are updating the record, we do not want to reset those fields back to what they were before the update. Also update the Show Snack Bar message to \u201cPlayer Updated.\u201d<\/li>\n<\/ul>\n\n\n\n<div class=\"wp-block-media-text is-stacked-on-mobile is-vertically-aligned-top\" style=\"grid-template-columns:33% auto\"><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/7gZeEifcRTiOlyR972RYATYroHEaffcjG8S4z5ChuwGH8rOUb90NaDGaZAPj6fDcVkyTeSoPb3ay4F1cV6fwxdF2XdYch4hgE7lpW61QnvMWybVmli0XMTuFrnHBcFFiGfSSXH8djeWegXBU6xwruJU\" alt=\"\"\/><\/figure><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\">Now all we need to do is set the currentPlayer parameter. We do this back on the HomePage. Select the ListTile and go into the Action Flow Editor. Add a Navigate action (to the UpdatePlayer page) and pass the current Supabase player row as currentPlayer.<\/p>\n<\/div><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<div class=\"wp-block-media-text is-stacked-on-mobile is-vertically-aligned-top\" style=\"grid-template-columns:32% auto\"><figure class=\"wp-block-media-text__media\"><img decoding=\"async\" src=\"https:\/\/lh7-us.googleusercontent.com\/rXYtZQjBWR9R_gWswj3dZHZODWI4uqV12H5x7bewniQp-3-IEwbSndlpOMMUrwdifPGkLexjM2eiaGWq9VE0F0YJUwpj9TBzdQR76VCGzDKsC0C1VbDCDF4bCvHX-dj5-388OPEaUzb8bf8wvE0n3xs\" alt=\"\"\/><\/figure><div class=\"wp-block-media-text__content\">\n<p class=\"wp-block-paragraph\">We should now have fully implemented CRUD processing for the player record. Test away.<\/p>\n<\/div><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Of course we skimped on validation. We certainly could have validated that the combination of first and last names wasn\u2019t duplicated, or even added an email address or a phone number to ensure uniqueness. This simple application was a way to introduce FlutterFlow and display basic features to developers and non-developers.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Supplemental information<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Besides the full breadth of UI widget options and properties, there are many other features that are part of FlutterFlow including:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/docs.flutterflow.io\/data-and-backend\/api-calls\" target=\"blank\" rel=\"noopener\">API calls<\/a> to interact with external services<\/li>\n\n\n\n<li>Ability to create <a href=\"https:\/\/docs.flutterflow.io\/customizing-your-app\/custom-functions\/custom-widgets\" target=\"blank\" rel=\"noopener\">custom widgets<\/a>&nbsp;<\/li>\n\n\n\n<li>Custom <a href=\"https:\/\/docs.flutterflow.io\/flutter\/custom-code-deep-dive\" target=\"blank\" rel=\"noopener\">functions and actions<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/docs.flutterflow.io\/advanced-functionality\/ai-gen\" target=\"blank\" rel=\"noopener\">AI usage<\/a> to generate code (Copilot), themes, components, pages (from a prompt)<\/li>\n\n\n\n<li><a href=\"https:\/\/docs.flutterflow.io\/deploying-your-app\/testing-your-app\/automated-tests\" target=\"blank\" rel=\"noopener\">Automated testing<\/a>&nbsp;<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">There are several levels of <a href=\"https:\/\/flutterflow.io\/pricing\" target=\"blank\" rel=\"noopener\">pricing<\/a> with FlutterFlow and the ability to download your code and do more traditional <a href=\"https:\/\/docs.flutterflow.io\/settings-and-integrations\/project-setup\/collaboration\" target=\"blank\" rel=\"noopener\">team collaboration<\/a>\/code repository development is in the higher pricing levels. Handing <a href=\"https:\/\/docs.flutterflow.io\/settings-and-integrations\/app-settings\/mobile-deployment\" target=\"blank\" rel=\"noopener\">mobile deployments<\/a> and sharing in-process work with clients is all integrated within FlutterFlow.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Overall, I enjoyed using FlutterFlow. As with all development tools, there are pros and cons. To summarize, I will list them here:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Cons<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>As a no-code\/low-code tool in which code can be downloaded, the main complaint about FlutterFlow is a fairly standard one. LIke other tools of this type, the code that gets created is not the most optimal and often requires&nbsp; changes, especially if the downloaded code has been updated.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>With all no-code\/low-code tools, you are more closely married to the tool which is sometimes more uncomfortable for developers who are used to the flexibility of swapping out architectural components or want to diverge from what the tool offers.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Pros<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>I was amazed at the breadth of user interface options available and how easily it is to adjust any aspect of the design of the mobile page.&nbsp;<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Many aspects of FlutterFlow were intuitive and seemed quite easy to use including templates, database integration, and functions.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">In summary, FlutterFlow is an excellent tool for either creating an MVP for a client or simply providing a mobile option for an enterprise system where cost and\/or time to market are a priority.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">At Solution Street we build mobile applications for MVP\u2019s and enterprise systems. Contact us if you can use our help!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction This is Part 2 (of 2) of my FlutterFlow tutorial. FlutterFlow is a no-code\/low-code browser-based builder for developing native mobile applications. In Part 1, I introduced FlutterFlow and created a mobile app with the basics of authentication using Sign Up\/Sign In page templates with a database connection to a Supabase database. In this final [&hellip;]<\/p>\n","protected":false},"author":6,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-6223","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>FlutterFlow Tutorial - Part 2 - Solution Street Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.solutionstreet.com\/blog\/2024\/04\/25\/flutterflow-tutorial-part-2\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"FlutterFlow Tutorial - Part 2 - Solution Street Blog\" \/>\n<meta property=\"og:description\" content=\"Introduction This is Part 2 (of 2) of my FlutterFlow tutorial. FlutterFlow is a no-code\/low-code browser-based builder for developing native mobile applications. In Part 1, I introduced FlutterFlow and created a mobile app with the basics of authentication using Sign Up\/Sign In page templates with a database connection to a Supabase database. In this final [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.solutionstreet.com\/blog\/2024\/04\/25\/flutterflow-tutorial-part-2\/\" \/>\n<meta property=\"og:site_name\" content=\"Solution Street Blog\" \/>\n<meta property=\"article:published_time\" content=\"2024-04-25T14:22:55+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-04-25T15:10:48+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.solutionstreet.com\/blog\/wp-content\/uploads\/2024\/04\/mobilephone3-Copytitle2.png\" \/>\n<meta name=\"author\" content=\"Peggy Frankel\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Peggy Frankel\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"15 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/2024\\\/04\\\/25\\\/flutterflow-tutorial-part-2\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/2024\\\/04\\\/25\\\/flutterflow-tutorial-part-2\\\/\"},\"author\":{\"name\":\"Peggy Frankel\",\"@id\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/#\\\/schema\\\/person\\\/c4846451eff30e9514b534b2a2e01696\"},\"headline\":\"FlutterFlow Tutorial &#8211; Part 2\",\"datePublished\":\"2024-04-25T14:22:55+00:00\",\"dateModified\":\"2024-04-25T15:10:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/2024\\\/04\\\/25\\\/flutterflow-tutorial-part-2\\\/\"},\"wordCount\":2178,\"commentCount\":0,\"image\":{\"@id\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/2024\\\/04\\\/25\\\/flutterflow-tutorial-part-2\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/04\\\/mobilephone3-Copytitle2.png\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/2024\\\/04\\\/25\\\/flutterflow-tutorial-part-2\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/2024\\\/04\\\/25\\\/flutterflow-tutorial-part-2\\\/\",\"url\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/2024\\\/04\\\/25\\\/flutterflow-tutorial-part-2\\\/\",\"name\":\"FlutterFlow Tutorial - Part 2 - Solution Street Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/2024\\\/04\\\/25\\\/flutterflow-tutorial-part-2\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/2024\\\/04\\\/25\\\/flutterflow-tutorial-part-2\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/04\\\/mobilephone3-Copytitle2.png\",\"datePublished\":\"2024-04-25T14:22:55+00:00\",\"dateModified\":\"2024-04-25T15:10:48+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/#\\\/schema\\\/person\\\/c4846451eff30e9514b534b2a2e01696\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/2024\\\/04\\\/25\\\/flutterflow-tutorial-part-2\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/2024\\\/04\\\/25\\\/flutterflow-tutorial-part-2\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/2024\\\/04\\\/25\\\/flutterflow-tutorial-part-2\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/04\\\/mobilephone3-Copytitle2.png\",\"contentUrl\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/wp-content\\\/uploads\\\/2024\\\/04\\\/mobilephone3-Copytitle2.png\",\"width\":1022,\"height\":429},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/2024\\\/04\\\/25\\\/flutterflow-tutorial-part-2\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"FlutterFlow Tutorial &#8211; Part 2\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/\",\"name\":\"Solution Street Blog\",\"description\":\"Quality Software Engineering - Technology and Consulting Articles\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/#\\\/schema\\\/person\\\/c4846451eff30e9514b534b2a2e01696\",\"name\":\"Peggy Frankel\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/af71ceb16f89d32c9bb825a47f8057da9283b4a27a934bf0c47cdef65ad0eb5d?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/af71ceb16f89d32c9bb825a47f8057da9283b4a27a934bf0c47cdef65ad0eb5d?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/af71ceb16f89d32c9bb825a47f8057da9283b4a27a934bf0c47cdef65ad0eb5d?s=96&d=mm&r=g\",\"caption\":\"Peggy Frankel\"},\"url\":\"https:\\\/\\\/www.solutionstreet.com\\\/blog\\\/author\\\/pfrankel\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"FlutterFlow Tutorial - Part 2 - Solution Street Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.solutionstreet.com\/blog\/2024\/04\/25\/flutterflow-tutorial-part-2\/","og_locale":"en_US","og_type":"article","og_title":"FlutterFlow Tutorial - Part 2 - Solution Street Blog","og_description":"Introduction This is Part 2 (of 2) of my FlutterFlow tutorial. FlutterFlow is a no-code\/low-code browser-based builder for developing native mobile applications. In Part 1, I introduced FlutterFlow and created a mobile app with the basics of authentication using Sign Up\/Sign In page templates with a database connection to a Supabase database. In this final [&hellip;]","og_url":"https:\/\/www.solutionstreet.com\/blog\/2024\/04\/25\/flutterflow-tutorial-part-2\/","og_site_name":"Solution Street Blog","article_published_time":"2024-04-25T14:22:55+00:00","article_modified_time":"2024-04-25T15:10:48+00:00","og_image":[{"url":"https:\/\/www.solutionstreet.com\/blog\/wp-content\/uploads\/2024\/04\/mobilephone3-Copytitle2.png","type":"","width":"","height":""}],"author":"Peggy Frankel","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Peggy Frankel","Est. reading time":"15 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.solutionstreet.com\/blog\/2024\/04\/25\/flutterflow-tutorial-part-2\/#article","isPartOf":{"@id":"https:\/\/www.solutionstreet.com\/blog\/2024\/04\/25\/flutterflow-tutorial-part-2\/"},"author":{"name":"Peggy Frankel","@id":"https:\/\/www.solutionstreet.com\/blog\/#\/schema\/person\/c4846451eff30e9514b534b2a2e01696"},"headline":"FlutterFlow Tutorial &#8211; Part 2","datePublished":"2024-04-25T14:22:55+00:00","dateModified":"2024-04-25T15:10:48+00:00","mainEntityOfPage":{"@id":"https:\/\/www.solutionstreet.com\/blog\/2024\/04\/25\/flutterflow-tutorial-part-2\/"},"wordCount":2178,"commentCount":0,"image":{"@id":"https:\/\/www.solutionstreet.com\/blog\/2024\/04\/25\/flutterflow-tutorial-part-2\/#primaryimage"},"thumbnailUrl":"https:\/\/www.solutionstreet.com\/blog\/wp-content\/uploads\/2024\/04\/mobilephone3-Copytitle2.png","inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.solutionstreet.com\/blog\/2024\/04\/25\/flutterflow-tutorial-part-2\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.solutionstreet.com\/blog\/2024\/04\/25\/flutterflow-tutorial-part-2\/","url":"https:\/\/www.solutionstreet.com\/blog\/2024\/04\/25\/flutterflow-tutorial-part-2\/","name":"FlutterFlow Tutorial - Part 2 - Solution Street Blog","isPartOf":{"@id":"https:\/\/www.solutionstreet.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.solutionstreet.com\/blog\/2024\/04\/25\/flutterflow-tutorial-part-2\/#primaryimage"},"image":{"@id":"https:\/\/www.solutionstreet.com\/blog\/2024\/04\/25\/flutterflow-tutorial-part-2\/#primaryimage"},"thumbnailUrl":"https:\/\/www.solutionstreet.com\/blog\/wp-content\/uploads\/2024\/04\/mobilephone3-Copytitle2.png","datePublished":"2024-04-25T14:22:55+00:00","dateModified":"2024-04-25T15:10:48+00:00","author":{"@id":"https:\/\/www.solutionstreet.com\/blog\/#\/schema\/person\/c4846451eff30e9514b534b2a2e01696"},"breadcrumb":{"@id":"https:\/\/www.solutionstreet.com\/blog\/2024\/04\/25\/flutterflow-tutorial-part-2\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.solutionstreet.com\/blog\/2024\/04\/25\/flutterflow-tutorial-part-2\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.solutionstreet.com\/blog\/2024\/04\/25\/flutterflow-tutorial-part-2\/#primaryimage","url":"https:\/\/www.solutionstreet.com\/blog\/wp-content\/uploads\/2024\/04\/mobilephone3-Copytitle2.png","contentUrl":"https:\/\/www.solutionstreet.com\/blog\/wp-content\/uploads\/2024\/04\/mobilephone3-Copytitle2.png","width":1022,"height":429},{"@type":"BreadcrumbList","@id":"https:\/\/www.solutionstreet.com\/blog\/2024\/04\/25\/flutterflow-tutorial-part-2\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.solutionstreet.com\/blog\/"},{"@type":"ListItem","position":2,"name":"FlutterFlow Tutorial &#8211; Part 2"}]},{"@type":"WebSite","@id":"https:\/\/www.solutionstreet.com\/blog\/#website","url":"https:\/\/www.solutionstreet.com\/blog\/","name":"Solution Street Blog","description":"Quality Software Engineering - Technology and Consulting Articles","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.solutionstreet.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.solutionstreet.com\/blog\/#\/schema\/person\/c4846451eff30e9514b534b2a2e01696","name":"Peggy Frankel","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/af71ceb16f89d32c9bb825a47f8057da9283b4a27a934bf0c47cdef65ad0eb5d?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/af71ceb16f89d32c9bb825a47f8057da9283b4a27a934bf0c47cdef65ad0eb5d?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/af71ceb16f89d32c9bb825a47f8057da9283b4a27a934bf0c47cdef65ad0eb5d?s=96&d=mm&r=g","caption":"Peggy Frankel"},"url":"https:\/\/www.solutionstreet.com\/blog\/author\/pfrankel\/"}]}},"_links":{"self":[{"href":"https:\/\/www.solutionstreet.com\/blog\/wp-json\/wp\/v2\/posts\/6223","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.solutionstreet.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.solutionstreet.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.solutionstreet.com\/blog\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/www.solutionstreet.com\/blog\/wp-json\/wp\/v2\/comments?post=6223"}],"version-history":[{"count":48,"href":"https:\/\/www.solutionstreet.com\/blog\/wp-json\/wp\/v2\/posts\/6223\/revisions"}],"predecessor-version":[{"id":6277,"href":"https:\/\/www.solutionstreet.com\/blog\/wp-json\/wp\/v2\/posts\/6223\/revisions\/6277"}],"wp:attachment":[{"href":"https:\/\/www.solutionstreet.com\/blog\/wp-json\/wp\/v2\/media?parent=6223"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.solutionstreet.com\/blog\/wp-json\/wp\/v2\/categories?post=6223"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.solutionstreet.com\/blog\/wp-json\/wp\/v2\/tags?post=6223"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}