Quasar & Vue 3: Drag & Drop, Touch Events & Parallax (Real World App #7)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this series i'm documenting my journey creating a real world app fudgit 2 from scratch using quasar 2 view 3 and the composition api an app that will ultimately be deployed to the ios android mac and windows app stores and in this episode i'm going to be talking about this swipe to reveal options functionality this drag to reorder items functionality how i created this swipe to go back functionality and this parallax effect that you can see between page transitions i'll also be showing you how this app is performing on a real device so far and i'll be sharing what i think of the composition api now having now used it on a real world project for several weeks make sure you subscribe and click the bell so you don't 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 been carrying on with the front end of this budget section i still have a long way to go with this section so i've added this new edit budget dialog which we can see if we click this button here and this is a lot like the add budget dialogue but it also has these buttons that the user can click as well and i wanted to give the user a shortcut to access some of these options so i've also added this swipe to reveal options functionality so the user can have a quick way of getting to these options and i've done this using quasars built-in touch events and i also wanted to give the user a way to reorder items so i've also added the ability to reorder items by drag and drop and i've done this using the view draggable package and when the user is on any kind of child page they can always go back by hitting the back button up here but i've also added the ability to swipe right to go back as well so if i swipe right we can also go back like that and you can see i have a nice little parallax effect as well between these page transitions so i've added that as well and back in video three i talked about these pane components and i mentioned that i have these spaces for the header and the footer within this cue scroll area because by default this scroll area goes right up to the top of the view and right down to the bottom here so i needed a spacer up here and down here to stop the content of the current pane going up behind the header or down below the footer so we can see a pane header spacer here and if i delete that you can see the content goes up behind the header and i mentioned that i would need to make the height of these spaces dynamic because sometimes the height of the header and the pane footer can change and i have managed to get this work in this week so that whenever the height of the header or the pane footer changes the height of these spaces will change as well so if we inspect the actual header this is currently 51 pixels tall and the pane header spacer is also 51 pixels tall and if i just jump to the header i'll change the height to let's say 100 pixels then we can see instantly that the pane header space a div has also been set to a height of 100 pixels and so when the header height changes we don't see our content disappear behind the new header and i've also been testing the app on a real device and i'll show you how it's looking later [Music] on let's see how this swipe to reveal options functionality is working so i'll jump to this component this budget list item component which is in source components budgets and budget list item dot view so this cue card component is this item here and in the last video i was actually using a v touch pan event on this component which allowed us to actually click and drag this over but that wasn't playing very nicely with the view draggable library which is used to reorder these items so you would click to drag on this item and it would just start firing the view draggable functionality so i've actually replaced that v touch pane event with these view touch swipe events instead so although we can no longer click and drag these items to the left we can achieve the same effect by just doing a quick swipe to the left to reveal the items and a quick swipe to the right to hide them so i have one v-touch swipe event for a left swipe by using this left modifier which will fire this swipe item left method and then another v-touch swipe event for a right swipe which will fire this swipe item write method so i'll jump down to these methods so here is the swipe item left method and this is first just going to check the distance that the user swiped by so i'm checking if they swiped by more than five pixels because i don't want this to be accidentally triggered if the user taps on this item and then if it is more than five pixels then we fire this move to offset min method which is here and this is basically just going to set the item offset value to our swipe offset min value and the item offset is bound to the style property on the cue card so i'm using transform translate x to move this card by whatever the value is in this item offset now this swipe offset min value which determines the amount that we want to move this item by in order to reveal the items i was previously declaring that variable right here and i was hard coding it i think it was set to like minus 200 or something like that but i'm now actually storing that value in my store in my budget store so i'll jump to store budgets so i'm storing that value here now and the reason i'm storing it here is because i realize that i need to make this value dynamic because sometimes the width of all of these items which get displayed can change so right now if i inspect this budget item that's been swiped across and the cue card is there so right now this has been offset by -205 pixels which reveals all of our items nicely but if i jump to the settings page and change the text size to extra-large jump back to the budgets page and swipe left you can see these items here are now much bigger and so the overall width of all of these options is wider which means i now need to adjust this offset accordingly so if i inspect this cue card now it's now being offset by minus 240 pixels so if this swipe offset min value was hard coded as 205 then we would find that we wouldn't be able to see our items underneath here so i'll just explain how i'm making this value dynamic so i'm going to jump to the budgets list component which is the parent component of these budget list item components so i have a ref on this div which is the parent element of this budgets list and if we jump down to the setup method i have a section of code here for figuring out the swipe offset width based on the width of the button icon list and the button icon list is this list of button icons here so i have an unactivated hook here which will be fired every time this list is activated so every time we navigate away and come back this hook will be activated and that's going to fire this calculate swipe offset min method here and then i'm basically just grabbing the first button icon list element so the first one of these by using that budgets list container ref ref and then using the query selector to grab the first button icon list and then i'm just grabbing the width of that button icon list and then i'm setting this swipe offset min value that's in the store to the width of this button icon list -5 which means that this offset will always be set to the exact width of this button icon list minus 5 pixels to give it a little bit of extra space so whenever the width of these items changes whether that's from changing the text size or changing the language because different languages might have longer words underneath these icons then this offset width will always update dynamically so this item will always swipe across enough to reveal all of our options okay so now i'll just show you the markup that i'm using for these button icons that you see here so i'll jump back to budgets list item.view and up to the template so here's our cue card here which we're able to swipe across and this is contained within this div which has a relative position and then directly after the cue card i have a div where the class of absolute to position it absolutely and within that we have our button icon list and this button icon list component if we open that up in buttons button icon list you can see this is just a q tabs component because i'm actually using quasar's q tabs component to display these and i know this isn't a typical way that you would use q tabs you would normally use them in your footer like i have down here however the style of cue tabs with the icon and the text underneath was exactly what i needed and it already has all of the click animations and stuff like that built in so i figured i might as well use it and so if we jump to this button icon component this is just a q tab component and i'm also using the same button icon list component button icon component which are in turn using cue tabs and cue tab components in this edit budget dialogue that you see down here as well [Music] let's take a look at this drag to reorder functionality and i don't think there's any way to do this that's built into quasar so i'm using a package called view draggable to do this and if your project is a view 3 project then you need to use the next version of view draggable so if you just google view draggable next and jump to this first link so this is the package i'm using and the way i got this up and running was i jumped to this live demos link and then i jumped to this transitions example because this has this nice little animation that you can see as we drag our items so then i just jump to view code i basically just copied all of the code from this example i just added it to my budgets list component i basically just repurposed it around my budgets list items but i haven't really done much differently here the only things i've done differently is i've used some css to hide this ghost item that you can see underneath the item that we're dragging see that little grayed out ghost item so i'm just using some css to hide that completely so we don't see those ghosts and i'm also using a little bit of css to add this yellow background to the item that we're dragging and i've also changed some of the default options so i'll just scroll down here so i've changed these options a little bit and i'm also storing these options in my store but that's really all i've done differently from this example so i'm going to jump to my store file store budgets and just show you these options so this animation option is just specifying the duration of the animation when we see the items jumping up and down in milliseconds this group option is basically just an id to identify this particular list and this disabled option is quite important because this option allows us to enable and disable this view draggable functionality and i'm actually doing that when i swipe left on an item to reveal options so at this point view draggable is actually disabled and i can't drag to reorder so if i just jump to budgets list item dot view and scroll down to this move to offset min method so you can see i'm actually triggering an action in my budget store here to disable draggable and that's here and i'm just simply setting this disabled option to false and then when we swipe this item back over to the right and this move to offset max method is fired i'm again firing the enable draggable action in my store to re-enable draggable so that we can start dragging our items again and this ghost class just adds a class to the ghost item that i mentioned before so that's the class that i'm using to actually hide that ghost item so if i just go to draggable.scss i'm just setting that goes to opacity zero so that we can't see it and this direction option means that we only want to drag items vertically and not horizontally and this delay option specifies a delay so that after you tap on an item and hold it will wait this long before the view draggable kicks in so on mobile we do have to tap and hold for a tiny little bit before we can actually drag and reorder our items but then this delay on touch only option which is set to true means that this delay will only happen on mobile devices but not on desktop so if i just switch to desktop view let's drag this over a bit reload on desktop there is no delay we can just click and drag these items straight away which i think is a bit more intuitive on desktop because on desktop apps you do generally expect to be able to drag things straight away and i did have some complaints about the original budget app on desktop because on budget one we still have that delay on desktop for dragging and reordering items and i still get quite a few people emailing me saying that they can't reorder items and that's because they don't expect to have to tap and hold before they drag and reorder things [Music] let's see what's going on with this swipe to go back functionality so basically any pane where we have a back button such as this budgets button here as well as clicking on that button to go back we can also swipe the pane right to go back as well so we can also see this working in our settings section if i go to the deepest point of the app which is this answer page we can swipe to go all the way back and this is kind of an expected user interface pattern on mobile these days especially on ios so i definitely wanted to get this working in this app so this is actually really simple i'm just going to jump to my pane component in source global pane and pane.view so again i'm using one of quasars v touch swipe events and i'm only listening for a right swipe and so whenever the user swipes right on one of these panes it's going to fire this swipe pane right method so i'll jump down to that and that's here and so before this method i'm just seeing if this current pane has a back button in its pane header so if i jump back up to the top i have a ref on this pane called pain ref and i have an unmounted hook here which will be fired every time a pain is loaded for the first time and i'm just using that ref that's on the parent component of the pane and using the query selector method to see if there's a button with this class pane header button back which all of these back buttons have that class so then when the user swipes right on a pane this method is fired and if there's a back button on this particular pane and if that swipe was a touch event and not a mouse event because we don't really need this functionality on desktop and this bit here is just checking to see if the right swipe occurred in the first 50 pixels of the pane first 50 horizontal pixels and if all of these things are true then we just simply trigger a click on the back button that's in the header and since these back buttons are already hooked up to change all of the state properties we need to slide a pane out of view then we don't need to do anything else we just need to trigger that click on this back button so if i swipe right on this pane here now all it's going to do is trigger a click on this settings button thus taking us back to the settings page and the reason i'm checking if the swipe is in the first 50 horizontal pixels of the pain is because it doesn't really make sense for a swipe over on the right here to trigger this back functionality it only makes sense if the user swipes over here and so if i add any more panes in future which are kind of child pains then i don't need to do anything fancy to get this swipe to go back functionality to work all i need to do is make sure there's a back button in the header with this class and i'm good to go let's look at this parallax effect that you can see when we navigate to child pages or when we go back again so if you just keep an eye on this settings pane while i tap on one of these options you'll see this settings pane slides slightly to the left and when we go back we can see that settings pane slide back to the right which gives this nice little ios style parallax effect and this is actually quite simple i'm just going to jump to my pain component in components global pain pain dot view so i have a new prop called nudge left which i've added here and i'm binding to the class attribute on the root component of this pane and i'm adding this nudge left class which is a computed property so i'll jump down to that which is here first i'm just making sure the value of that nudge left prop is not undefined and if the value of that nudge left prop is true then we just add this pane nudge left class to the root element of this pane component so i'll just jump to the inspector and if i just find this div the root div of this paint which is here and if i add a class of pain dash nudge dash left you can see all this class is doing is using transform and translate x to nudge the pane 90 pixels to the left so then when we remove that class we see it nudge back to the right again so if i jump to a component which is using this nudge left prop such as this settings component so i'll jump to components settings and settings dot view so we can see i'm using this nudge left prop and the value i'm passing in is store.settings.state.sectionactive and if i jump to my settings store scroll down that's this property here in my state and so this is set to null by default but when we tap on settings option then this will be set to something like account or appearance or dates and we're then sliding that settings section into view so once this property section active is set to a value it will then be truthy which means this pane nudge left class will be added to the pane thus pushing it to the left so now all i need to do to achieve this nudge left effect is just add this nudge left prop to a pane and assign this to a truthy value so back in video three i went into detail about these pain components and i explained that they're made up of a pain header component a pain footer component and a pain body component which is this scrollable area and i have the pain body component open here and i explained that i have these two space divs one called pain header spacer which was set to the height of the actual header and one called pain footer spacer which was set to the height of the pane footer and i mentioned that at some point i would need to make the height of these spaces dynamic so that if the height of the pane header or the pane footer changes then the height of the relevant spacer would also change and i've now managed to make the height of these spaces change dynamically according to the underlying height of the header and footer but before i explain how i've done that i'll just demonstrate what these spacers are doing and why i need them so i'm just going to change my layout to iphone 5 here just so that the content of this page is actually longer than the height of the pane body so that we need to scroll i'm just going to zoom in a little bit here so you can see right now we can scroll all the way down to the bottom of the content in this pane and nothing is being obscured by the pane header or the pane footer but if i just jump to the inspector and i jump to this cue scroll area which is the pain body and look for these spaces so we can see them here we have the pain header spacer and the paint footer spacer just drag this over a little bit and so if i delete the pane footer spacer and we scroll down we can no longer see all of the content of this pane because it's being obscured by this pane footer and likewise if i delete the pane header spacer then we see the content of our pane go up behind the header so that's why we need these spaces so i'll just undo those deletions but why do i need the height of these spaces to be dynamic well i'm just going to switch back to iphone 678 layout and increase the zoom to 125 and i'm going to jump to the budgets page and i'm actually just going to add a load of budgets here so that we have a scrollable pane so i'm going to jump to store budgets i'm just going to duplicate these two budget items a bunch of times and save that and these now go right off the page so we have to scroll down to see them all so right now we can see everything on the page no problem and if i inspect this pane footer here it's currently 62 pixels tall and if i find the pane footer spacer which is here that's also 62 pixels tall however if i jump to the settings page and appearance and i changed the text size to extra-large and jump back to the budgets page and inspect the footer again the pane footer this is now 73 pixels tall because we increased the text size of this button which increased the height of the button which also increased the height of the pane footer so in order for us to still be able to see all of our content at the bottom of the pane then we also need to set the footer spacer to the same height 73 pixels which if we just look for that spacer we can see it is 73 pixels tall and there are other things besides changing the text size which could change the height of the pane footers and headers so if i just jump to my design i have this all budgets balance widget and this is actually toggleable by the user so the user can hide this or show this at any time so that's just another thing which would change the height of the pain footer so i needed to listen out for any change in the height to the pain header or the pain footer regardless of what caused it to also trigger a change in height to the spacers as well so i'll try and explain how this is working so i'm going to jump to pain dot view which is the main pain component and i'll scroll down a bit so i'm handling all of this stuff here so i have an unmounted hook which will be fired when any pane is first mounted then i'm just getting a reference to the pain header the pain header spacer the pain footer and the pain footer spacer and then i'm using the resize observer to watch the pain header and the pain footer for changes in height so if i just google resize observer then you can learn more about this on the mozilla page and it says here the resize observer interface reports changes to the dimensions of an element's content or border box so i'm just using this to set up two resize observers one for the pane header and one for the pane footer and to initialize these i'm just checking if there is a pane header on the current pane and if so i'm firing the observe method on either the pane header or the pane footer so that means that the code inside these resize observers will be fired every time the dimensions of the pane header or the pane footer change so let's say the user changes the text size and that increases the height of the header then this hook will be fired and all we're doing is grabbing the paint header spacer and setting the height to the new height of the pane header and the same is all true for the pane footer so now if anything whatsoever changes the height of the paint header or paint footer regardless of what caused it then the height of the relevant spacer will also be instantly changed so even if we manually change the height of the header in the inspector then this will still work so right now the pane header is 51 pixels tall and if we look for the pain header spacer that's also 51 pixels tall so if i just jump back to the pane header and manually set the height to let's say 100 pixels and we look at the pane header spacer we can see that instantly the pane header spacer has also been changed to a height of 100 pixels [Music] so i was highly skeptical about the composition api at first and i didn't really like it the options api always made sense to me and it was the simplicity of the options api which drew me towards vue in the first place more so than the other big frameworks but as you can probably tell by now i've decided to use the composition api throughout the app and there are two main reasons for this number one is that i'm already using the composition api for my state management and number two is that i've seen evidence in the view three source code which suggests to me that view 3 might be more optimized for the composition api than the options api and also that the view developers might consider the options api as legacy now so this is from the view three source code and we see this test here which refers to the options api as legacy options and in this other bit of code we also see an interface called legacy options and in this bit of code here we can see that if we use options api hooks they're converted into composition api hooks under the hood so it looks to me like extra code is being fired under the hud when we use the options api in a view 3 project and now i don't know this for certain and i'm not stating this as a fact but this implies to me that there could possibly be a performance hit when using the options api in a view 3 project and again i don't know this for sure it could be that there's no performance difference whatsoever if we use the options api but performance is so critical to me for this app that any small bit of doubt makes me want to use the composition api but what do i think about the composition api now having used it for several weeks on a real world project well after a shaky start i've got to say that i'm actually starting to quite like it now and i can explain why by looking at my pain component which is one of my more complex components so far so i'll jump to source components global pain and pain dot view so in this component in my setup function i have four different sets of functionality so i have some code here which manages the pane position classes for the desktop version i have some code here for managing the nudge left class which creates the parallax effect then i have some code here for handling the swipe left to go back and then i have some code for watching changes to the height of the pane header or pane footer and setting the spaces to the same height now using the composition api i've been able to keep all of these separate functionalities together in standalone blocks of code without anything being scattered all over the place whereas if i'd used the options api for this component then i wouldn't have been able to do that because for example i have a computed property here and a computed property here and these computed properties are completely unrelated but if i'd used the options api then i would have had to bundle these computed properties together in the computed option and if i scroll down a bit this bit which handles the swipe to go back and this bit which watches for changes to the pane header and footer these are both using unmounted hooks but using the composition api i've been able to keep this functionality where it belongs in the appropriate block of code whereas if i'd used the options api then this code here and all of this code here would have been bundled together in a single mounted hook and also if i'd use the options api and we look at this swipe right to go back code then this variable this code in the unmounted hook and this swipe pane right method would all have been separated because the variable would have been in the data method and this bit would have been in the mounted hook and this method would have been in the methods option so even though there are still some things i don't like about the composition api like having to import things from view all the time and having to return everything at the bottom of the setup method i think the fact that i can keep all of my relevant functionality together like this in organized blocks more than makes up for those little annoyances and i think the value of being able to do this will become more apparent as the app gets more complicated and as i start adding data to the app and more complicated logic etc and by the way let me know in the comments what you think of the composition api so far let us know what your experience has been like so finally i just want to show you the performance of fudgit 2 so far on a real device so what you can see on the screen here is my iphone xs and when i run the app on a real device in development mode it was a little bit slow which got me a little bit nervous but then i built the app for production and launched that app on the real device and the performance has absolutely blown me away so right now i don't have any apps running on the phone so i'm going to start this from a cold boot so i'm going to tap on the icon and you can see the uploads instantly there's no lag or delay in loading the app and if we navigate through all of the pages the pages all load instantly and again there's no delay or lag or anything um when we navigate through nested pages so if i go to the settings section and then down through the help section all the animations are super smooth and the parallax effect is super smooth uh when we swipe to go back it's again all super smooth and if we go to a really long page then scrolling down all of the content is again super smooth we get the nice little bounce at the top and bottom and all the button animations and stuff like that are super smooth and if i jump back to the settings page and appearance if we change the language it changes instantly there's no flicker or delay or anything just instantly changes and the same for the theme as well if we change that just changes instantly and the same for text size as well that just instantly changes all of the text size in the app and i'll just set the text size back and jump to the budgets page so the swipe to reveal options again is super smooth and silky and the animations on the buttons are really nice as well and the drag to reorder again the animation on that is just super smooth and also all of the dialogues they appear super smoothly and disappear really smoothly as well so everything is just super fast and snappy and this isn't a brand new device it's an iphone xs from 2018 over two and a half years old and even on this the app just feels completely native to me and i just hope that this performance continues when i start adding data to the app and start adding all of the real guts of the app but for now i'm super happy with this performance [Music] so i'm going to carry on working on this budget section i still have quite a lot to do here such as adding this all budgets balance widget adding these tool tips and adding a folder item like this and adding these drawers and adding this multiple selection thing as well let me know in the comments if you would do any of this stuff differently or if you have any questions and check out the link to 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 thanks for watching and i'll see you in the next one
Info
Channel: Make Apps with Danny
Views: 2,845
Rating: undefined 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: _wAW8_9h2FQ
Channel Id: undefined
Length: 35min 2sec (2102 seconds)
Published: Wed May 26 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.