diff options
Diffstat (limited to 'www/crm/wp-content/plugins/civicrm/civicrm/ang/crmRouteBinder.md')
-rw-r--r-- | www/crm/wp-content/plugins/civicrm/civicrm/ang/crmRouteBinder.md | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/www/crm/wp-content/plugins/civicrm/civicrm/ang/crmRouteBinder.md b/www/crm/wp-content/plugins/civicrm/civicrm/ang/crmRouteBinder.md new file mode 100644 index 00000000..a297bdc4 --- /dev/null +++ b/www/crm/wp-content/plugins/civicrm/civicrm/ang/crmRouteBinder.md @@ -0,0 +1,106 @@ +# crmRouteBinder + +Live-update the URL to stay in sync with controller data. + +## Example + +```js +angular.module('sandbox').config(function($routeProvider) { + $routeProvider.when('/example-route', { + reloadOnSearch: false, + template: '<input ng-model="filters.foo" />', + controller: function($scope) { + $scope.$bindToRoute({ + param: 'f', + expr: 'filters', + default: {foo: 'default-value'} + }); + } + }); +}); +``` + +Things to try out: + + * Navigate to `#/example-route`. Observe that the URL automatically + updates to `#/example-route?f={"foo":"default-value"}`. + * Edit the content in the `<input>` field. Observe that the URL changes. + * Initiate a change in the browser -- by editing the URL bar or pressing + the "Back" button. The page should refresh. + +## Functions + +**`$scope.$bindToRoute(options)`** +*The `options` object should contain keys:* + + * `expr` (string): The name of a scoped variable to sync. + * `param` (string): The name of a query-parameter to sync. (If the `param` is included in the URL, it will initialize the expr.) + * `format` (string): The type of data to put in `param`. May be one of: + * `json` (default): The `param` is JSON, and the `expr` is a decoded object. + * `raw`: The `param` is string, and the `expr` is a string. + * `int`: the `param` is an integer-like string, and the expr is an integer. + * `bool`: The `param` is '0'/'1', and the `expr` is false/true. + * `default` (object): The default data. (If the `param` is not included in the URL, it will initialize the expr.) + * `deep` (boolean): By default the json format will be watched using a shallow comparison. For nested objects and arrays enable this option. + +## Suggested Usage + +`$bindToRoute()` was written for a complicated routing scenario with +multiple parameters, e.g. `caseFilters:Object`, `caseId:Int`, `tab:String`, +`activityFilters:Object`, `activityId:Int`. If you're use-case is one or +two scalar values, then stick to vanilla `ngRoute`. This is only for +complicated scenarios. + +If you are using `$bindToRoute()`, should you split up parameters -- with +some using `ngRoute` and some using `$bindToRoute()`? I'd pick one style +and stick to it. You're in a complex use-case where `$bindToRoute()` makes +sense, then you already need to put thought into the different +flows/input-combinations. Having two technical styles will increase the +mental load. + +A goal of `bindToRoute()` is to accept inputs interchangably from the URL or +HTML fields. Using `ngRoute`'s `resolve:` option only addresses the URL +half. If you want one piece of code handling all inputs the same way, you +should avoid `resolve:` and instead write a controller focused on +orchestrating I/O: + +```js +angular.module('sandbox').config(function($routeProvider) { + $routeProvider.when('/example-route', { + reloadOnSearch: false, + template: + '<div filter-toolbar-a="filterSetA" />' + + '<div filter-toolbar-b="filterSetB" />' + + '<div filter-toolbar-c="filterSetC" />' + + '<div data-set-a="dataSetA" />' + + '<div data-set-b="dataSetB" />' + + '<div data-set-c="dataSetC" />', + controller: function($scope) { + $scope.$bindToRoute({expr:'filterSetA', param:'a', default:{}}); + $scope.$watchCollection('filterSetA', function(){ + crmApi(...).then(function(...){ + $scope.dataSetA = ...; + }); + }); + + $scope.$bindToRoute({expr:'filterSetB', param:'b', default:{}}); + $scope.$watchCollection('filterSetB', function(){ + crmApi(...).then(function(...){ + $scope.dataSetB = ...; + }); + }); + + $scope.$bindToRoute({expr:'filterSetC', param:'c', default:{}}); + $scope.$watchCollection('filterSetC', function(){ + crmApi(...).then(function(...){ + $scope.dataSetC = ...; + }); + }); + } + }); +}); +``` + +(This example is a little more symmetric than a real one -- because the A, +B, and C datasets look independent. In practice, their loading may be +intermingled.) |