/usr/share/civicrm/ang/crmRouteBinder.md is in civicrm-common 4.7.30+dfsg-1ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 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.)
|