Commit | Line | Data |
---|---|---|
67341f3c CW |
1 | # crmRouteBinder |
2 | ||
3 | Live-update the URL to stay in sync with controller data. | |
4 | ||
5 | ## Example | |
6 | ||
7 | ```js | |
8 | angular.module('sandbox').config(function($routeProvider) { | |
9 | $routeProvider.when('/example-route', { | |
10 | reloadOnSearch: false, | |
11 | template: '<input ng-model="filters.foo" />', | |
12 | controller: function($scope) { | |
13 | $scope.$bindToRoute({ | |
14 | param: 'f', | |
15 | expr: 'filters', | |
16 | default: {foo: 'default-value'} | |
17 | }); | |
18 | } | |
19 | }); | |
20 | }); | |
21 | ``` | |
22 | ||
23 | Things to try out: | |
24 | ||
25 | * Navigate to `#/example-route`. Observe that the URL automatically | |
26 | updates to `#/example-route?f={"foo":"default-value"}`. | |
27 | * Edit the content in the `<input>` field. Observe that the URL changes. | |
28 | * Initiate a change in the browser -- by editing the URL bar or pressing | |
29 | the "Back" button. The page should refresh. | |
30 | ||
31 | ## Functions | |
32 | ||
284ed4f0 CW |
33 | **`$scope.$bindToRoute(options)`** |
34 | *The `options` object should contain keys:* | |
35 | ||
36 | * `expr` (string): The name of a scoped variable to sync. | |
37 | * `param` (string): The name of a query-parameter to sync. (If the `param` is included in the URL, it will initialize the expr.) | |
38 | * `format` (string): The type of data to put in `param`. May be one of: | |
39 | * `json` (default): The `param` is JSON, and the `expr` is a decoded object. | |
40 | * `raw`: The `param` is string, and the `expr` is a string. | |
41 | * `int`: the `param` is an integer-like string, and the expr is an integer. | |
42 | * `bool`: The `param` is '0'/'1', and the `expr` is false/true. | |
43 | * `default` (object): The default data. (If the `param` is not included in the URL, it will initialize the expr.) | |
44 | * `deep` (boolean): By default the json format will be watched using a shallow comparison. For nested objects and arrays enable this option. | |
67341f3c CW |
45 | |
46 | ## Suggested Usage | |
47 | ||
48 | `$bindToRoute()` was written for a complicated routing scenario with | |
49 | multiple parameters, e.g. `caseFilters:Object`, `caseId:Int`, `tab:String`, | |
50 | `activityFilters:Object`, `activityId:Int`. If you're use-case is one or | |
51 | two scalar values, then stick to vanilla `ngRoute`. This is only for | |
52 | complicated scenarios. | |
53 | ||
54 | If you are using `$bindToRoute()`, should you split up parameters -- with | |
55 | some using `ngRoute` and some using `$bindToRoute()`? I'd pick one style | |
56 | and stick to it. You're in a complex use-case where `$bindToRoute()` makes | |
57 | sense, then you already need to put thought into the different | |
58 | flows/input-combinations. Having two technical styles will increase the | |
59 | mental load. | |
60 | ||
61 | A goal of `bindToRoute()` is to accept inputs interchangably from the URL or | |
62 | HTML fields. Using `ngRoute`'s `resolve:` option only addresses the URL | |
63 | half. If you want one piece of code handling all inputs the same way, you | |
64 | should avoid `resolve:` and instead write a controller focused on | |
65 | orchestrating I/O: | |
66 | ||
67 | ```js | |
68 | angular.module('sandbox').config(function($routeProvider) { | |
69 | $routeProvider.when('/example-route', { | |
70 | reloadOnSearch: false, | |
71 | template: | |
72 | '<div filter-toolbar-a="filterSetA" />' | |
73 | + '<div filter-toolbar-b="filterSetB" />' | |
74 | + '<div filter-toolbar-c="filterSetC" />' | |
75 | + '<div data-set-a="dataSetA" />' | |
76 | + '<div data-set-b="dataSetB" />' | |
77 | + '<div data-set-c="dataSetC" />', | |
78 | controller: function($scope) { | |
79 | $scope.$bindToRoute({expr:'filterSetA', param:'a', default:{}}); | |
80 | $scope.$watchCollection('filterSetA', function(){ | |
81 | crmApi(...).then(function(...){ | |
82 | $scope.dataSetA = ...; | |
83 | }); | |
84 | }); | |
85 | ||
86 | $scope.$bindToRoute({expr:'filterSetB', param:'b', default:{}}); | |
87 | $scope.$watchCollection('filterSetB', function(){ | |
88 | crmApi(...).then(function(...){ | |
89 | $scope.dataSetB = ...; | |
90 | }); | |
91 | }); | |
92 | ||
93 | $scope.$bindToRoute({expr:'filterSetC', param:'c', default:{}}); | |
94 | $scope.$watchCollection('filterSetC', function(){ | |
95 | crmApi(...).then(function(...){ | |
96 | $scope.dataSetC = ...; | |
97 | }); | |
98 | }); | |
99 | } | |
100 | }); | |
101 | }); | |
102 | ``` | |
103 | ||
104 | (This example is a little more symmetric than a real one -- because the A, | |
105 | B, and C datasets look independent. In practice, their loading may be | |
106 | intermingled.) |