Quasar & Vue 3: Screen Plugin & Advanced State Management (Real World App #4)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this series i'm documenting my journey creating a real world app budget 2 from scratch using quasar 2 view 3 and composition api an app that will ultimately be deployed to the ios android mac and windows app stores and in this episode i'll be covering this settings page which loads all of its sections and fields from my custom composition api state management store which has a completely different interface for desktop and mobile uses adaptive props to style things differently on desktop and mobile and i'll also be covering async components how to keep your pages alive in a view 3 project and more make sure you subscribe and click the bell if you don't want to miss any of the videos in this series and check out the link to the whole playlist in the description [Music] so this week i've basically finished the front end for this settings page for both desktop and mobile and it has a completely different interface for desktop and mobile so on desktop we have these links to the different sections on the side and these will load the section on the right here whereas on mobile we have a pane with all of the links to the different sections and when we click that we load a new pane with that section and i've also set up a state management store using the composition api to store all of the different sections and all of the fields as well so all of these sections and all of these fields are actually coming from my settings store here and i've also got basic internationalization working and theme switching and text resizing as well [Music] so in terms of design i have changed this settings page quite a bit from the original design if i just open that up the sketch file this is the original settings design and i only ever actually designed it for mobile and in the design i had all of the different sections and all the different fields just on a single page like this which would have made a really really long page and so i decided that even though it would have been much easier to build it like this in just one page that it just wasn't really user friendly to have the user scrolling down all of these settings and also this design wouldn't have really worked on desktop because it would have meant that all of these options would have been stretched right across this settings pane which wouldn't have looked very good so i decided that on desktop i would have a little side menu at the side here with all the different sections that we can click through and i would load each section over on the right here and for mobile i initially had everything on the page like this but in an accordion style so you would click on an item such as account and it would pop down an accordion with all of the account fields and it took me ages to get that working well i just decided it was a little bit clunky so i decided instead on mobile to just have a page with the menu with all the different setting sections and then to load in each section in a new pane like this and then the user can just tap to go back to the menu so i think this is a much better experience for the user than this would have been [Music] so i'll try to explain how i created this adaptive interface which is completely different on mobile desktop so if i jump to components settings and settings dot view this is the component for this whole settings pane and if we look in the pane body here we have a column which is this first column here and inside that column we have the settings menu and this column is being displayed on both desktop and mobile and i'm basically just using css to stretch this out to full width on mobile and then after this first column i'm spitting out another component here this settings section desktop component and this component contains another column and another component with all of the settings sections and if i just jump back to settings.view so this component with the second column is only being displayed on desktop and it's only being rendered on desktop and i'm using the screen plugin to do that and i'm going to get into the screen plug-in in a little bit so this will actually only be rendered on desktop but then on mobile i'm spitting out a different component after the pain component this settings sections mobile component and if i open that up this is actually another pane component because if i just jump to mobile view if we click on a settings option it actually loads a new pane here with all of the fields for that section and we can get back to the list of options by clicking this settings button and again this component is only going to be rendered on mobile again i'm using the screen plugin to make sure that this is only rendered on mobile and if i jump back to this settings section mobile component you can see i have a transition component on here with the slide in right animation and the slide outright animation which is how i'm animating in the pane with this animation and making it disappear with the slide out animation and if we look in the pane body of this settings section mobile component i'm spitting out this settings sections component which contains all of these sections and then on the settings sections desktop component i'm spitting out that same component with all the sections except it's going to be inside this second column [Music] if you look at this settings menu here this settings menu component is being used on both mobile and desktop but they have a completely different design so on mobile this list has a white background it has a border and it has separators between all of the items so on mobile this is using the separator prop and the bordered prop whereas if we look at this on desktop this now has a transparent background and it no longer has a border and it no longer has separators so initially i was actually spitting out two different menu components one for mobile and one for desktop i really didn't like that because duplication is a cardinal sin in development but i couldn't figure out how to conditionally add different props to quasar components on different screen sizes but then i discovered the screen plugin so if i jump to the quasar site and this is the version two docs and if we go to options and helpers and screen plugin it tells you how to use the screen plugin here so you can see an example here where we're conditionally spitting out the dense prop so all we need to do is dollar q dot screen and then dot lt.md or gt.sm and this way we can conditionally spit out props depending on the size of the browser so in this case this is only going to add the dense prop to this list if the user's screen is less than the medium break point so if i jump to settings menu dot view so this is this menu component and you can see here i'm using the screen plugin to only add the bordered prop if the screen is less than the medium break point and the same for the separator prop as well and i'm also using the screen plugin to conditionally output classes only on mobile as well to give it the white background and the rounded borders that we can see on mobile i'm also using the screen plugin to conditionally output this chevron icon you can see on the right here on mobile as well because we don't see those chevrons on desktop and i'm also using the screen plugin in a few different places so if i go to settings section dot view i'm using it to conditionally output text size classes for desktop and mobile as well in the settings section here so this title at the top here is much bigger on desktop than it is on mobile and i'm also using the screen plugin on the main settings.view component to only render the mobile settings section pane which you see here on mobile and to only render the desktop settings sections column on desktop so this screen plugin is unbelievably handy if you're creating an app for multiple platforms and i'm extremely happy that i've discovered it [Music] so all of these settings sections and all of the fields in each section are all being completely managed by my store so if i go to store settings and store settings.js so i have this settings object in my state with an object for each section and i'll just collapse these so you can see what's going on so you can see i have an object for each section account appearance dates currency etc and if i open one of these up we have a label property which is specifying the title for the section which you can see in the menu and also here at the top of the section and then we have an icon property which is specifying the icon that's going to be used both here and here and then we have a fields object which is going to contain all the different fields for that section so this budget pro subscription object is this field here this first field so each field has a type because i've got different kinds of fields in this section so this field item type is just kind of a simple clickable link like these ones but then i also have a select field type and a checkbox field type and a radio list field type and i have individual components for all these different field types so if i go to components settings and fields you can see all of these components here field checkbox field input field item field radio and field select and some fields also have click handler options as well so if i jump to the account section and i click on this first item you can see this value here changes so we can easily add click handlers for item fields like this and some fields also have options and value properties such as the select options and the select options also have a change method that can be fired when a select is changed so i can easily fire code within my store whenever the user interacts with one of these field types and keeping all of my settings sections and fields in the store like this is going to make it really easy to manage and it's really going to reduce the room for error because i don't have to mess around with components every time i want to add a new setting or a new field i don't need to mess around with the menu component whenever i make changes because everything is coming from this store which means that all i need to do if i want to add a new settings section or a new field it's just add to this object here so i'll just collapse these again so let's say i want to add a new settings section all i need to do is add a new object here it doesn't really matter what we call this object so i'll just call it penguin um we need to give it a label so i'll set the label to penguin and we need to give it an icon as well so i'll set the icon property to this linux icon i've got in my clipboard which is a fun awesome icon and if i save that you can see we now have a new section called penguin and we can see this on both desktop and mobile as well and if we want to add some fields to this section we can just add a fields object and stick our fields in here so a lot of field called hook the penguin we need to specify the type so i'll set the type to field dash item then we need to give it a label so i'll set the label to poke the penguin and i'll save that and we can now see this item on the page and we should be able to see it on both desktop and mobile and so if we want to do something when the user clicks on this then we can just add a click handler to this field like this and i'll just alert something out are you sure you wanna poke the penguin save that and if i now click this item we see that alert so i did have one major issue with this approach to generating all of these setting sections and fields based on this store so if i jump to the social section i have this join the budget newsletter widget here and this is not really a field it's more of a widget and it's going to have lots of different functionality such as display in this second field when the user starts typing in this email field and it's also going to have validation and form submission and stuff like that so it made sense to have this in its own component so if i just jump to the social section in the store and this join newsletter field i've actually set up a special type of field here called field component where we can actually load any component that we want and all we need to do is pass in the path to that component so if i jump to settings fields and field component so in this component i just have a component component which is used for displaying components dynamically and i'm just setting the is prop to this comp which is a computed property and then i'm just using the define async component method to import the component that's specified here in this component property in the store dynamically and i did have a really annoying issue with this and it took me ages to get it working for some reason this import statement doesn't work unless you have some of the start of your path value as a string so you can see i have a string here slash components slash and then this path here but originally i had the whole path in this string so if i just copy in fact i'll cut this source component slash bit and save that i'll just paste it at the start of the path here and save that so now all of the path in this import method is coming from a variable and for some reason this just doesn't work we can't see the join component and if i open up the console we see this cannot find module so slash component slash settings join newsletter dot view even though that component exists and the path is exactly the same as it was before so i'll just put this back how it was and yeah for some reason if you put a bit of a string at the start of this value for this import method then it works now we can see the widget again and i don't know why this is happening i don't know if it's a bug or whatever and if you know why it's happening then please let us know down in the comments but for now if i have any other widgets that i want to put in my settings section widgets that are going to have complex functionality then i can easily do that using the define async component method so i wanted all of the pages of this app to keep alive so that for example if the user is on the budgets page and they have a particular budget open and they're scrolled down to a particular position in that budget because these can get quite long and then they jump to the settings page make some changes and jump back to the budgets page i wanted everything to be preserved now in quasar 1 and view 2 you could just jump to the layout file so layouts main layout.view and you could just surround this router view component in the q page container component in keeper live tags like that and you were good to go however in quasar 2 and view 3 we get this warning in the console which says router view can no longer be used directly inside of transition or keep alive use slot props instead but thankfully it gives us the solution right here so we can just copy this code from the console and paste it over all of this and we're good to go and now all of our pages are keeping alive however i still had an issue with these scroll areas that are in these pane components and just to demonstrate that i'll jump to this pain body component which is in components global pain pain body and i'm just going to comment out all this code i've added here which i'll explain in a minute i'll remove this scroll event i'll save that so even though all of these pages are keeping alive if i scroll down a bit in this pane on the left here so you can see right now there's a button at the top and if i scroll down a little bit jump to a different page and jump back again you can see we're right back at the top of the scroll area so by default these scroll areas don't maintain their scroll position if you navigate away and come back again so i'll just put this code back in in this pain body component so to fix this issue these q scroll area components have this scroll event that we can listen to which is fired every time one of these scroll areas is scrolled and they also have this set scroll position method that we can fire to set the vertical scroll position on these scroll areas so all i've done here is add a ref to the scroll area and set up a ref variable to store the current scroll position and then when the scroll event is fired i'm firing this on scroll method here and this returns an object called info with the current vertical scroll position so basically every time this is scrolled i'm grabbing that vertical scroll position and storing it in this scroll position ref variable and then i have an unactivated hook which will be fired every time we come back to this scroll area where i'm just grabbing the scroll area using this scroll area ref and then firing the set scroll position method and setting the vertical scroll position based on the value that's in this scroll pause ref variable so now if i scroll down a little bit uh jump to a different page and jump back again then we're right where we were so i also have some basic language switching working theme switching and text size switching as well now the theme switching and the text size switching is working in the exact same way that i explained in video 2 in this series so there's nothing to report there but the language switching was a bit more tricky because remember all of these settings sections and fields are coming from my store file in store settings store settings.js and all of the reactions to changes in these fields are being fired in this store file as well in these change methods or click methods and if we jump to the quasar site and options and helpers and app internationalization and we jump down to create language switcher it only tells you how to switch language in a component file but i want to switch language in this store file and i also couldn't find how to do this on the view i18n website so i basically just tried a few different things and eventually got it working so quasar has already set up this i18n boot file in the boot folder which is exporting this i18n object so all we need to do in our store file is import this so i'm just importing that from the boot file then if i jump down to the appearance language field so this change method is fired when we change this drop down here to change the language all we need to do is i18n.global.local equals and then the locale code and we can also use our translation fields in our store file if we want to by just grabbing t from i18n.global like this and then we can just grab a translation like this with the t method so if i jump to the i18n folder enus this index.js so what i've done here is just going to grab this field here with the property name account um this does work however when you change language it doesn't update all of these fields in your state so what i'm doing instead to ensure that all of this text that comes from this state can be translated in the view is i'm sending this label value to the view and if i just jump to components settings and settings menu so that label property is coming through here and i'm basically just firing the translation helper at this point on the label which is going to grab the appropriate translation from the translation file and so this way if i just save this we change language we can see all these labels in the menu being translated and for now i'm not translating everything basically just the page names and all of these settings section names and i probably won't add all of the translations and all of the different fields until i've pretty much finished the app and i was thinking actually it could get pretty tricky to manage all of these translation files once i have tons and tons of different phrases that are being translated and tons of different languages as well this could get pretty difficult to manage so one thing i was thinking of doing at some point is creating a csv file something like this with a column for each language with the language name and the language locale code and then all of the phrases going down here and then i was thinking of creating a node script which would pass that csv file and loop through each language and each phrase generating all of the folders that we need in this i18n folder and all of these index.js files as well with all of the different phrases so let me know what you think about that idea and let me know if you have any tips that could help me do that because i haven't got a clue how to do that at the moment [Music] so what i'm going to do next is this help section do the front end for that because if i jump to the design we have this help section here with a bunch of different common questions and also a search box which will display some questions based on search criteria and then when we tap on a question we go to this answer page where the user can find the answer so i'll probably just do the front end for this and then i'll probably do the front end for this account section with these login register pages and this budget plus pop-up which encourages the user to buy the budget plus subscription and you may have noticed that i'm doing all of the boring stuff first here the settings page on this account page the reason being that usually when i create an app i do all the interesting stuff first all of the core functionality and then what happens is i get right to the end of the project and i'm already really fed up with working on it and then i've got to go and do all the boring stuff like the settings page and at that point in the project it's really painful to have to do all of that stuff when your motivation is starting to wear thin so i decided this time as much as possible i'm going to try and get all of the boring stuff done first and do the interesting stuff last so let me know in the comments if you would do any of this stuff differently uh let me know if you have any questions about any of this stuff and you can check out the full playlist in the description uh please hover over my face and click subscribe if you don't want to miss any of the videos in this series uh thanks for watching and i'll see you in the next one [Music]
Info
Channel: Make Apps with Danny
Views: 3,236
Rating: 4.969697 out of 5
Keywords: android, app design, app development, app development process, app ideas, app success, building an app, cordova, create a real world app, create an app, creating an app, css, electron, firebase, firebase cloud firestore, how to create a successful app, how to launch an app, how to start an app business, html, ios, javascript, mac, make money with apps, quasar, quasar framework, quasar framework tutorial, real app, real world app, successful app launch, vue, vue.js, vuejs, windows
Id: SiQUlLSa4sA
Channel Id: undefined
Length: 25min 13sec (1513 seconds)
Published: Wed Apr 28 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.