3.5 Adding More Functionality to the App
We've still got a few features left to implement before the test app can be considered complete. Let's finish this off in this lesson before we move on to some of the more advanced topics.
1.Introduction2 lessons, 06:55
2.RequireJS Basics4 lessons, 27:18
3.Handling Common Tasks5 lessons, 51:21
4.Advanced4 lessons, 22:08
5.Conclusion1 lesson, 02:59
3.5 Adding More Functionality to the App
Hey there. Our app is still missing some key features that we would need to add before we could even consider it for a beta release. Let's tie the remaining things together in this lesson. Before we move onto some of the more advanced topics that we'll at before the end of the course. So each task has a delete link to remove the individual task. Let's get that working first of all. Remember earlier in the course, when we configured Require to use the non-AMD script file smoke signals? This is one of the situations where we need to make use of cross-module messaging. Without getting tangled up in dependencies. The delete link is part of the task, so really its functionality belongs in the taskViewModel. But it's the ListViewModel that contains the array of tasks. And we need to be able to remove the task from the array as well as from the page. So we can remove the task from the page in the taskViewModel. And then use smoke signals to message to the list that the task should be removed from the array. So first of all we need to include smoke signals in the ListViewModel. [BLANK_AUDIO] The dependency array in this module is now getting a bit out of control. This would probably be about the time that I'd switch to using the simple, common js wrapper format for specifying them instead. Which would make the module a bit more readable. We won't worry about that for now, but do bear in mind when you're creating your own modules. So in the addTask method, we can convert the taskViewModel to make it able to emit events. [BLANK_AUDIO] So we give our view model the methods that it needs to omit events using the smokesignals.convert method. So now we just need to specify an event handler for a custom event. And we do that using the on method that the smokesignals.convert method adds onto our view model. [BLANK_AUDIO] So we specify a handler called removeTaskHandler, which we can also add. [BLANK_AUDIO] We use bind again to use this naturally inside the actual worker method. All we need to do is splice the task out of the array. In the taskViewModel, we can deal with removing the task from the page. [BLANK_AUDIO] And we'll also need to bind to the deleteTaskHandler from the taskView. [BLANK_AUDIO] Great, so now we should find that we can remove tasks from our list. [BLANK_AUDIO] So, one more thing we can add is the functionality of the check box which denotes whether the task is complete or not. This can be handled with a combination of simple CSS bindings and a class name when the task is marked as complete. And an event binding on the input to handle the checking or unchecking of the box. In the taskViewModel first, let's add the following computed function. [BLANK_AUDIO] Each time the value of the completed observable changes, this function will be invoked. If the completed observable has a truthy value, the task name complete will be returned. If it's false, an empty string is returned. So now we can add the following event handler. [BLANK_AUDIO] All we need to do here is invert the value of the completed observable and then return true. We have to return true in all cases or the checked state of the check box will never change. So now let's add the bindings for this to the taskView. [BLANK_AUDIO] So now when we add tasks, we should find that when we check the check box, the complete class is applied. And we see the complete styling. Let's just check that that's happening. [BLANK_AUDIO] So it's not working at the moment. Let's see if there's any errors in the console. Nothing in the console. And let's try using a different binding. [BLANK_AUDIO] So there's one more thing that we need to do. And that is make the task as completed in the array of tasks contained by the list. To handle this, we can use another smoke signals event. In the taskViewModel, we can omit the tasks completed event in the total taskCompleted method. Now back in the ListViewModel, we can add a handler for this event. [BLANK_AUDIO] So, to update the task we get the array index that the task is at, and use this to invert the value of the completed property of the task. Lastly we can bind to the smoke signals events in the addTask method. [BLANK_AUDIO] And now the actual underlying array of tasks will be updated also. Keeping the array of tasks up to date is important for when we want to save the list. Speaking of which, before we finish up for today, let's wire up the save button so that we can save our list. We can add the code to save list to the list manager. Although we'll need to add the button handler to the ListViewModel, because the button is part of the list UI. In the list manager then, we'll need to add the storage module as a dependency. Then we can add a saveList function. [BLANK_AUDIO] It takes a list as an argument and then invokes the save method of the storage module, passing it the list to save. Don't forget we're using the exports pattern in this module. So, we'll need to export the new method. [BLANK_AUDIO] Now back in the ListViewModel, we can add a handler that we can bind to the button in IU. In which will invoke the new saveList method on the list manager. The ListViewModel should therefore take a dependency on the list manager. [BLANK_AUDIO] And lastly, let's just bind the save button and the view to this new method [BLANK_AUDIO] That should just about do it. Let's go back to the browser now. [BLANK_AUDIO] And now when we save the list, we should be able to inspect our local storage area. So, we're seeing a binding error. Let's just take a quick look at that. So it can't find our saveList handler. And we just need to tell it that it's in the listViewModel. [BLANK_AUDIO] That's looking more promising. So we might need to come back to the page before we actually see that. [BLANK_AUDIO] Great, so again, in this slightly long lesson, we've mostly been tying up the functionality of the app. And generally, getting a feel for building an app using Require. We touched quite a lot of modules in this lesson. But, as you can see, because we're using a modular structure that RequireJS enforces everything is nicely organized. And when we want to update or add something, we know exactly where we need to go to do it. Thanks for watching.