@@ -2939,31 +2939,109 @@ test.only('9. Routing > should allow me to display active/completed/all items',
2939
2939
2940
2940
#### 9. Routing _ Implementation_
2941
2941
2942
+ Given that we are using "hash" based routing,
2943
+ where the content of the app changes in response to the hash portion of the URL
2944
+ implementing routing is a matter of _ filtering_ the Todo List items
2945
+ in response to the hash.
2946
+
2947
+ There 3 steps to implementing this:
2948
+
2949
+ 1 . Create an Event Listener for the ` window.onhashchange ` event
2950
+ which invokes ` signal('ROUTE') ` .
2951
+
2952
+ 2 . Create a ` 'ROUTE' ` case in the ` update ` function
2953
+ which sets the ` model.hash ` value.
2954
+
2955
+ 3 . Based on the ` model.hash ` value defined above,
2956
+ filter the ` model.todos ` .
2957
+
2942
2958
Since this is the _ final_ quest in the TodoMVC/Todo List App,
2943
- the solution is _ not_ included here.
2944
- Spend some time trying to make the test assertions pass.
2959
+ the we encourage you to attempt to write this
2960
+ before/without looking at the "solution".
2961
+
2962
+ Remember that you only want to write the _ minimum_ code
2963
+ necessary to make the test assertions pass.
2945
2964
2946
2965
If you get "_ stuck_ " consult the code in ` todo-app.js ` .
2947
2966
2948
- #### 9.1 Routing _ Bonus_
2949
2967
2950
- As a _ bonus_ level,
2951
- you can add the following event listener to your ` subscriptions `
2952
- to make the router work when the url (hash) changes in the browser:
2968
+ #### 9.1 Routing _ Event Listener_
2969
+
2970
+ Add the following event listener to your ` subscriptions `
2971
+ to "listen" for when the URL hash changes:
2972
+
2953
2973
2954
2974
``` js
2955
2975
window .onhashchange = function route () {
2956
2976
signal (' ROUTE' )();
2957
2977
}
2958
2978
```
2959
- And the ` 'ROUTE' ` ` case ` to your ` update ` function:
2979
+
2980
+ #### 9.2 ROUTE ` case `
2981
+
2982
+ Add the ` 'ROUTE' ` ` case `
2983
+ to your ` update ` function:
2984
+
2960
2985
``` js
2961
2986
case ' ROUTE' :
2962
2987
new_model .hash = (window && window .location && window .location .hash ) ?
2963
2988
window .location .hash : ' #/' ;
2964
2989
break ;
2965
2990
```
2991
+ *** OR*** , if you are confident that your app
2992
+ will _ always_ run in a Web Browser with a ` window.location.hash ` property:
2993
+
2994
+ ``` js
2995
+ case ' ROUTE' :
2996
+ new_model .hash = window .location .hash ;
2997
+ break ;
2998
+ ```
2966
2999
3000
+ #### But _ Why...?_
3001
+
3002
+ ** Question** : Why do we "copy" the ` window.location.hash `
3003
+ to ` model.hash ` instead of just "getting" it from ` window.location.hash `
3004
+ each time we need to know what the hash is? <br />
3005
+
3006
+ ** Answer** : technically, we could _ avoid_ having
3007
+ the ` 'ROUTE' ` case in ` update ` completely
3008
+ and just use the ` window.location.hash `
3009
+ instead of ` model.hash ` ,
3010
+ the _ reason_ we add this "step"
3011
+ is that we want to have a "single source of truth" in the ` model ` .
3012
+ This is a _ good_ habit to have
3013
+ as it makes _ debugging_ your application
3014
+ _ much_ easier because you _ know ** exactly** _
3015
+ what the "full state" of the application is/was at any point in time.
3016
+
3017
+ You will often read/hear the expression "_ easier to ** reason about** _ ",
3018
+ all this means is that you can "work through" something in your head
3019
+ without getting "confused" by having "too many things to keep track of".
3020
+
3021
+
3022
+ #### 9.3 _ Filter_ the ` model.todos ` based on ` model.hash `
3023
+
3024
+ We need to do the filtering "_ non-destructively_ ",
3025
+ so it needs to happen in the ** ` view ` ** (_ just before rendering_ )
3026
+ rather than
3027
+
3028
+ > _ ** Question** : is this "** logic in the view** "...?_ <br />
3029
+ > _ ** Answer** : ** Yes** , it is ** presentation logic** .
3030
+ The ` view ` function, ** ` render_main ` in this case
3031
+ is merely ** filtering** the data ** non-destructively** before rendering it.
3032
+ Using ` Array.filter ` is a "fancy" (concise) way of writing an ` if ` statement.
3033
+ ` if ` statements are "OK" in views because they are
3034
+ "conditional presentation logic"
3035
+ i.e. only show this section ` if ` a certain variable is set. <br />_
3036
+ _ By using ` Array.filter ` followed by ` Array.map ` we render a ** subset**
3037
+ of the ` model.todos ` ** without** "** mutating** " the ` model.todos ` Array.
3038
+ In other words if the URL hash is ` '#/completed' `
3039
+ the user only wants to see the "completed" items,
3040
+ we don't want to "lose" the todos that are not yet complete,
3041
+ we just want to "hide" them temporarily,
3042
+ if we were to apply this filter in the ` update ` function it would
3043
+ "lose" the other todos (i.e. destroy the data!)
3044
+ the best way to filter data non-destructively is in the ** view** _
2967
3045
2968
3046
# Done!
2969
3047
0 commit comments