From 53898fe30ecbb4b4752559d52de2eb3197e0b24e Mon Sep 17 00:00:00 2001 From: hunternovak Date: Tue, 15 Aug 2017 10:18:55 -0700 Subject: [PATCH 01/13] Starting v4 documentation updates. Adding gitignore file. --- .gitignore | 27 ++++++++++++++++++++++++++ README.md | 4 ++++ best-practices.md | 32 ++++++++++++++++++++++--------- concepts/components/components.md | 23 +++++++++++++--------- 4 files changed, 68 insertions(+), 18 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c9f1a1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,27 @@ +## Idea project file +*.iml + +## Directory-based project format: +.idea/ + +## File-based project format: +*.ipr +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties + + diff --git a/README.md b/README.md index f425416..41e0f80 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,8 @@ wilson.utility('MyUtility', [..., function(...) { }]); wilson.class('MyClass', [..., function(...) { }]); wilson.filter('MyFilter', [..., function(...) { }]); + +wilson.router([..., function(...) { }]); ``` Although this initial declaration is not specifically on the 'angular' global instance, under-the-hood, wilson @@ -47,6 +49,8 @@ wilson.class() ---> angular.factory() wilson.utility() ---> angular.factory() wilson.filter() ---> angular.filter() + +wilson.router() ---> angular.factory() ``` Wilson ensures that some base options provided to angular so that these constructs are represented appropriately, but as diff --git a/best-practices.md b/best-practices.md index ad58357..4566334 100644 --- a/best-practices.md +++ b/best-practices.md @@ -12,8 +12,11 @@ This is the recommended pattern: ```js wilson.component('my-component', { + transclude: true, // Optional scriptDependencies: [], // Optional scope: {}, // Optional + exports: {}, // Optional + inherit: {}, // Optional require: [], // Optional controller: [function() {}], // Required link: function($scope, $element, $attrs, controller) {} // Optional @@ -24,22 +27,34 @@ wilson.component('my-component', { ___ -**2 *Avoid using "this" to reference a controller instance. Store a local "controller" reference.*** +**2 *Avoid using "this" in a component controller. Use private functions or declare them on the $scope so that they can be used in from the view.*** + +Wilson components treat $scope as the effective controller. All controller functions should be declared privately or +publicly (on the $scope instance). This keeps consistency in the pattern that $scope represents a component instance. -This makes access to the controller instance very explicit. It also keeps consistency with the -"controller" parameter in the **link** method. This "controller" reference should be declared as the -first line of each component controller. ```js wilson.component('my-component', { controller: ['$scope', function($scope) { - var controller = this; // This is recommended in every controller + + function foo = function foo(msg) { // GOOD - Explicit private function only available inside this controller + alert(msg); + }; + + $scope.bar = function bar(msg) { // GOOD - Explicit $scope function available in the controller and view + alert(msg); + }; + + this.foobar = function foobar(msg) { // BAD - "this" is on the controller which is not used + alert(msg); + }; + }] }); ``` ___ -**3 *Declare explicit function names for all $scope and controller functions*** +**3 *Declare explicit function names for all $scope functions*** This makes debugging much easier for the developer. If an error prints to the console, the stack trace will have a function name to point out where the problem occurred. Without it the @@ -48,15 +63,14 @@ console will print "Anonymous Function" which is ambiguous and does not help wit ```js wilson.component('my-component', { controller: ['$scope', function($scope) { - var controller = this; - + $scope.message = ''; $scope.updateMessage = function updateMessage(message) { // GOOD - Function name matches the property name $scope.message = message; }; - controller.clearMessage = function() { $scope.message = ''; }; // BAD - Function has no name + $scope.clearMessage = function() { $scope.message = ''; }; // BAD - Function has no name }] }); ``` diff --git a/concepts/components/components.md b/concepts/components/components.md index d2c600b..8f7cb7a 100644 --- a/concepts/components/components.md +++ b/concepts/components/components.md @@ -24,7 +24,6 @@ Example component: ```js wilson.component('nav-bar', { controller: ['$scope', '$location', function($scope, $location) { - var controller = this; $scope.navOptions = [ { name: 'Home', target: '/home' }, @@ -71,14 +70,14 @@ a component and start using it...Magic. Apart from dependency resolution, wilson also applies specialized base functionality onto each component. This ensures that each component has the same base interface and gives the developer access to -common functions and utilities, which helps to eliminate boiler plate and code duplication. These -special decorations are split between the $scope and the controller instance of a component. +common functions and utilities, which helps to eliminate boiler plate and code duplication. Specifically, each +component's $scope is decorated with a special interface that makes it a wilson component. -[See the code in ComponentFactoryService](https://github.com/hightail/wilson/blob/3.0.0/lib/client/src/services/ComponentFactoryService.js) +[See the code in ComponentFactoryService](https://github.com/hightail/wilson/blob/4.0.0/lib/client/src/services/ComponentFactoryService.js) # $scope decorations -* [componentCName](#componentCName) +* [component](#component) * [parentComponent](#parentComponent) * [stateMachine](#stateMachine) * [defaultValue](#defaultValue) @@ -86,14 +85,20 @@ special decorations are split between the $scope and the controller instance of * [bindToDigest](#bindToDigest) -## $scope.componentCName +## $scope.component -A string representing the name of the component. This is the same name that is used in the component -declaration. +An object representing the identification metadata of the component. ```typescript -componentCName: string; +component: object; +``` +Properties: +```json +{ + "id": "" +} ``` + Usage Example: ```js wilson.component('nav-bar', { From 2ed6673ae66adda5826e3aa81ff74ae44f5896b3 Mon Sep 17 00:00:00 2001 From: Hunter Novak Date: Tue, 29 Aug 2017 13:07:31 -0700 Subject: [PATCH 02/13] Updated component and best-practices sections with v4 updates. --- best-practices.md | 4 +- concepts/components/components.md | 414 +++++++++++------------------- 2 files changed, 148 insertions(+), 270 deletions(-) diff --git a/best-practices.md b/best-practices.md index 4566334..b112fcf 100644 --- a/best-practices.md +++ b/best-practices.md @@ -37,11 +37,11 @@ publicly (on the $scope instance). This keeps consistency in the pattern that $s wilson.component('my-component', { controller: ['$scope', function($scope) { - function foo = function foo(msg) { // GOOD - Explicit private function only available inside this controller + function foo(msg) { // GOOD - Explicit private function only available inside this controller alert(msg); }; - $scope.bar = function bar(msg) { // GOOD - Explicit $scope function available in the controller and view + $scope.bar = function bar(msg) { // GOOD - Explicit $scope function available in the controller and view alert(msg); }; diff --git a/concepts/components/components.md b/concepts/components/components.md index 8f7cb7a..de15b85 100644 --- a/concepts/components/components.md +++ b/concepts/components/components.md @@ -73,16 +73,24 @@ ensures that each component has the same base interface and gives the developer common functions and utilities, which helps to eliminate boiler plate and code duplication. Specifically, each component's $scope is decorated with a special interface that makes it a wilson component. -[See the code in ComponentFactoryService](https://github.com/hightail/wilson/blob/4.0.0/lib/client/src/services/ComponentFactoryService.js) +[See the code in ComponentFactoryService](https://github.com/hightail/wilson/blob/4.1.2/lib/client/src/services/ComponentFactoryService.js) # $scope decorations * [component](#component) -* [parentComponent](#parentComponent) -* [stateMachine](#stateMachine) +* [state](#state) * [defaultValue](#defaultValue) +* [translate](#translate) * [triggerDigest](#triggerDigest) * [bindToDigest](#bindToDigest) +* [stateMachine](#stateMachine) +* [storage.get](#storageGet) +* [storage.set](#storageSet) +* [on.event](#onEvent) +* [on.signal](#onSignal) +* [on.watch](#onWatch) +* [on.digest](#onDigest) +* [on.pageUnload](#onPageUnload) ## $scope.component @@ -90,12 +98,13 @@ component's $scope is decorated with a special interface that makes it a wilson An object representing the identification metadata of the component. ```typescript -component: object; +component: Object; ``` Properties: ```json { - "id": "" + "id": "bd671303-2a19-4ab2-c175-9c3cb591ac09", // Unique Id for this instance + "name": "nav-bar" // Name of the component } ``` @@ -103,84 +112,24 @@ Usage Example: ```js wilson.component('nav-bar', { controller: ['$scope', function($scope) { - var message = 'This is the ' + $scope.componentCName + ' component'; + var message = 'This is the ' + $scope.component.name + ' component'; wilson.log.info(message); // --> "This is the nav-bar component" }] }); -``` - -## $scope.parentComponent - -The scope of this component's parent wilson component (aka it's containing component). This gives components access -(if necessary) to the scope of their parent. If this is a page-level component parentComponent will be null. - -> IMPORTANT: **parentComponent** is not necessarily the direct parent $scope, but the $scope of the parent wilson component. - -```typescript -parentComponent: Object; -``` -Example Parent: - -**todo-list.html** -```html -
-
    -
  • - -
  • -
-
-``` -**todo-list.js** -```js -wilson.component('todo-list', { - controller: ['$scope', function($scope) { - var controller = this; - - $scope.todoList = [{ name: 'Go to the store' }, { name: 'Make Dinner' }, { name: 'Walk the dog'}]; - }] -}); -``` -Example Child: - -**todo.html** -```html -
-

[[name]]

- -
-``` -**todo.js** -```js -wilson.component('todo', { - scope: { - todo: '=todo' - }, - controller: ['$scope', function($scope) { - var controller = this; - - $scope.markComplete = function markComplete() { - $scope.todo.complete = true; - }; - - wilson.log.info($scope.parentComponent); // --> This is the todo-list component $scope - wilson.log.info($scope.parentComponent.todoList); // --> [{ name: 'Go to the store }, ...] - }] -}); -``` +```` -## $scope.stateMachine +## $scope.state A special stateMachine object that can be used to add state-based control to a component. Uses the [javascript-state-machine library](https://github.com/jakesgordon/javascript-state-machine). ```typescript -stateMachine: Object; +state: Object; ``` -See details below for the [setState() method](#setState). +See details below for the [stateMachine() method](#stateMachine). ## $scope.defaultValue(scopePropertyName, defaultValue) @@ -206,6 +155,30 @@ wilson.component('nav-bar', { }); ``` + +## controller.translate(text, options) + +Translate a text string using the i18next service. Used for internationalizing dynamic strings +during run-time of the application. Accepts the original text and returns a translated string. + +```typescript +function translate(text: string, options: Object): string; +``` +Usage Example: +```js +wilson.component('my-component', { + controller: ['$scope', function($scope) { + + // Translate to Spanish + var translatedText = $scope.translate('Where is my dog?', { lng: 'es' }); + + wilson.log.info(translatedText); // --> "Donde esta mi perro?" + + }] +}); +``` + + ## $scope.triggerDigest() Triggers an angular digest cycle. This method will not throw an exception if a digest is in progress (in the event that a @@ -264,197 +237,26 @@ wilson.component('my-component', { > for demonstration purposes. In practice developers should use the $timeout service which will trigger a digest > by default -# Controller decorations - -* [translate](#translate) -* [overrideText](#overrideText) -* [getPersistentValue](#getPersistentValue) -* [setPersistentValue](#setPersistentValue) -* [setPersistentValues](#setPersistentValues) -* [watchAndPersist](#watchAndPersist) -* [setState](#setState) -* [auto.on](#autoOn) -* [auto.add](#autoAdd) -* [auto.watch](#autoWatch) -* [auto.afterDigest](#autoAfterDigest) - - -## controller.translate(text, options) - -Translate a text string using the i18next service. Used for internationalizing dynamic strings -during run-time of the application. Accepts the original text and returns a translated string. - -```typescript -function translate(text: string, options: Object): string; -``` -Usage Example: -```js -wilson.component('my-component', { - controller: ['$scope', function($scope) { - var controller = this; - - // Translate to Spanish - var translatedText = controller.translate('Where is my dog?', { lng: 'es' }); - - wilson.log.info(translatedText); // --> "Donde esta mi perro?" - }] -}); -``` - -## controller.overrideText(overrideNamespace, textKey, overrideText) - -Add an override translation mapping for a component namespace. Used for detailed customization of i18n strings -in a specific context. - -```typescript -function overrideText(overrideNamespace: string, textKey: string, overrideText: string): void; -``` -Usage Example: -```js -wilson.component('my-component', { - controller: ['$scope', function($scope) { - var controller = this; - - controller.overrideText($scope.componentCName, 'Where is my dog?', 'Donde esta mi gato?') - - // Translate to Spanish - var translatedText = $scope.translate('Where is my dog?', { lng: 'es' }); - - wilson.log.info(translatedText); // --> "Donde esta mi gato?" - }] -}); -``` - -## controller.getPersistentValue(key, defaultValue) - -Retrieve a value from this component's localStorage namespace at a given key. If the value does not exist -return the specified defaultValue, otherwise return null. - -```typescript -function getPersistentValue(key: string, defaultValue: any): any; -``` -Usage Example: -```js -wilson.component('dashboard', { - controller: ['$scope', function($scope) { - var controller = this; - - $scope.viewMode = controller.getPersistentValue('viewMode', 'list-view'); - - wilson.log.info($scope.viewMode); // --> "list-view" - - controller.setPersistentValue('viewMode', 'grid-view'); // --> sets 'viewMode' to local storage - - $scope.viewMode = controller.getPersistentValue('viewMode', 'list-view'); - - wilson.log.info($scope.viewMode); // --> "grid-view" - }] -}); -``` - -## controller.setPersistentValue(key, value) - -Store a value to this component's localStorage namespace at a given key. This will persist in the browser -indefinitely and will be retained when the browser is refreshed or even closed. - -```typescript -function setPersistenValue(key: string, value: any): any; -``` -Usage Example: -```js -wilson.component('dashboard', { - controller: ['$scope', function($scope) { - var controller = this; - - controller.setPersistentValue('viewMode', 'grid-view'); - - $scope.viewMode = controller.getPersistentValue('viewMode', 'list-view'); - - wilson.log.info($scope.viewMode); // --> "grid-view" - }] -}); -``` - -## controller.setPersistentValues(obj) - -Store a set of key/values to this component's localStorage namespace. Returns an object that -contains all stored key/values for this component's namespace. This will persist in the browser -indefinitely and will be retained when the browser is refreshed or even closed. - -```typescript -function setPersistentValues(obj: Object): Object; -``` -Usage Example: -```js -wilson.component('dashboard', { - controller: ['$scope', function($scope) { - var controller = this; - - controller.setPersistentValues({ viewMode: 'grid-view', welcomeMessage: 'Hello World' }); - - $scope.viewMode = controller.getPersistentValue('viewMode'); - $scope.welcomeMessage = controller.getPersistentValue('welcomeMessage'); - - wilson.log.info($scope.viewMode); // --> "grid-view" - wilson.log.info($scope.welcomeMessage); // --> "Hello World" - }] -}); -``` - -## controller.watchAndPersist(key, defaultValue) - -Setup a $scope.$watch on the given key that stores the value to this component's localStorage namespace -when the value changes. Stores the defaultValue if the watched value becomes falsey. - -```typescript -function watchAndPersist(key: string, defaultValue: any): void; -``` -Usage Example: -```js -wilson.component('dashboard', { - controller: ['$scope', '$timeout', function($scope, $timeout) { - var controller = this; - - $scope.message = 'Hello'; - - controller.watchAndPersist('message', 'Foo'); // Start the watch - - $scope.updateMessage = function updateMessage(message) { - $scope.message = message; - }; - - $scope.updateMessage('World'); // Update the message - this will trigger the watch - - $timeout(function() { - var storedMessage = controller.getPersistentValue('message'); - - wilson.log.info(storedMessage); // --> "World" - The message will be set in localStorage - }) - }] -}); -``` - -## controller.setState(config, callback) +## $scope.stateMachine(config, callback) Setup a bindable stateMachine on the component $scope. Uses the [javascript-state-machine library](https://github.com/jakesgordon/javascript-state-machine) to create a state-based control concept for a component. This method takes a specific configuration object unique to the [StateMachine.create()](https://github.com/jakesgordon/javascript-state-machine#usage) method of javascript-state-machine. ```typescript -function setState(config: Object, callback: Function): void; +function stateMachine(config: Object, callback: Function): void; ``` Usage Example: ```js wilson.component('dashboard', { controller: ['$scope', '$timeout', function($scope, $timeout) { - var controller = this; $scope.message = 'Please Wait...'; // Setup the stateMachine - controller.setState({ + $scope.stateMachine({ initial: 'Loading', events: [ { name: 'loaded', from: 'Loading', to: 'Ready' }, @@ -472,13 +274,13 @@ wilson.component('dashboard', { }); $timeout(function() { - $scope.stateMachine.loaded(); + $scope.state.loaded(); - wilson.log.info($scope.stateMachine.current); // --> "Ready" + wilson.log.info($scope.state.current); // --> "Ready" wilson.log.info($scope.message); // --> "Dashboard Ready" }); - wilson.log.info($scope.stateMachine.current); // --> "Loading" + wilson.log.info($scope.state.current); // --> "Loading" wilson.log.info($scope.message); // --> "Please Wait..." }] }); @@ -513,22 +315,79 @@ Each timeout entry supports 4 properties: | **refreshEvent** | no | An event that will reset the timeout if not yet completed | -# Controller event handlers +# Storage Helpers + +Wilson component scopes are decorated with special storage helper methods for setting and getting localStorage data that +is specific to the component itself. This data is stored to a component-namespaced key that isolates the values stored +from other components. These values should be explicitly set and cleared from the component scope. + +## $scope.storage.get(key, defaultValue) + +Retrieve a value from this component's localStorage namespace at a given key. If the value does not exist +return the specified defaultValue, otherwise return null. + +```typescript +function get(key: string, defaultValue: any): any; +``` +Usage Example: +```js +wilson.component('dashboard', { + controller: ['$scope', function($scope) { + + $scope.viewMode = $scope.storage.get('viewMode', 'list-view'); + + wilson.log.info($scope.viewMode); // --> "list-view" + + $scope.storage.set('viewMode', 'grid-view'); // --> sets 'viewMode' to local storage + + $scope.viewMode = $scope.storage.get('viewMode', 'list-view'); + + wilson.log.info($scope.viewMode); // --> "grid-view" + + }] +}); +``` + +## $scope.storage.set(key, value) + +Store a value to this component's localStorage namespace at a given key. This will persist in the browser +indefinitely and will be retained when the browser is refreshed or even closed. + +```typescript +function set(key: string, value: any): any; +``` +Usage Example: +```js +wilson.component('dashboard', { + controller: ['$scope', function($scope) { + + $scope.storage.set('viewMode', 'grid-view'); + + $scope.viewMode = $scope.storage.get('viewMode', 'list-view'); + + wilson.log.info($scope.viewMode); // --> "grid-view" + + }] +}); +``` + + +# Event Helpers The component controller interface contains a special set of event handlers under the **auto** sub-property. These methods provide the same functionality as the original handling methods, but are auto cleaned up when the scope of the component is destroy. This allows developers to use them freely without having to worry about memory/reference management. -## controller.auto.on(eventName, handler) +## $scope.on.event(eventName, handler) Alias for $scope.$on. See [angularjs documentation](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on). ```typescript -function on(eventName: string, handler: Function): void; +function event(eventName: string, handler: Function): void; ``` -## controller.auto.watch(key, handler) +## $scope.on.watch(key, handler) Alias for $scope.$watch. See [angularjs documentation](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watch). @@ -536,24 +395,32 @@ Alias for $scope.$watch. See [angularjs documentation](https://docs.angularjs.or function watch(key: string, handler: Function): void; ``` -## controller.auto.add(signal, handler) +## $scope.on.signal(signal, handler) Alias for signal.add. See [js-signal documentation](http://millermedeiros.github.io/js-signals/docs/symbols/Signal.html#add). ```typescript -function add(signal: Signal, handler: Function): void; +function signal(signal: Signal, handler: Function): void; ``` > EXPLAINED: This method attaches the **handler** to the **signal** by calling the signal.add. -## controller.auto.afterDigest(handler) +## $scope.on.digest(handler) Run the given handler after each digest cycle completes. ```typescript -function afterDigest(handler: Function): void; +function digest(handler: Function): void; ``` +## $scope.on.pageUnload(handler, includeLocalNav) + +Run the given handler when the pages is about to unload. If **includeLocalNav** is true, then also +run on local page navigation. + +```typescript +function pageUnload(handler: Function, includeLocalNav: boolean): void; +``` # Advanced Component Features @@ -564,7 +431,10 @@ give flexibility to developers when determining the best way to structure their Each component supports a special html attribute called "expose". This attribute can be applied to a component when it is used in a template and must be supplied a property name as the attribute value. When applied, the sub-component will -decorate its $scope onto the parent component $scope at the specified property. +decorate any **exports** onto it's parent component $scope. + +When using the expose attribute an **exports** object should be included in the component definition. This object represents +an explicit map of properties that will be "exposed" on the parent component scope. Example: @@ -578,38 +448,47 @@ Example: ```js wilson.component('dashboard', { controller: ['$scope', '$timeout', function($scope, $timeout) { - var controller = this; - wilson.log.info($scope.newsFeed); // --> This will be null at construction time (since parents load prior to children) + wilson.log.info($scope.newsFeed); // --> This will be null at construction time (since parents load prior to children) $timeout(function() { - wilson.log.info($scope.newsFeed.feed); // --> [{ id: '1234', title: 'Stocks up 20%' }] - referenced from news-feed's $scope + wilson.log.info($scope.newsFeed.feed); // --> [{ id: '1234', title: 'Stocks up 20%' }] - referenced from news-feed's $scope + wilson.log.info($scope.newsFeed.trending); // --> undefined (this was not included in the exports object)) }); + }] }); ``` **news-feed.js** ```js wilson.component('news-feed', { + exports: { + feed: 'feed' + }, controller: ['$scope', function($scope) { - var controller = this; - $scope.feed = [{ id: '1234', title: 'Stocks up 20%' }]; + $scope.feed = [{ id: '1234', title: 'Stocks up 20%' }]; + $scope.trending = [{ id: '5678', title: 'Some Political BS' }]; + }] }); ``` -In our example above, the news-feed component decorates its $scope onto dashboard as **newsFeed**. This allows the -dashboard component to access the $scope of its child at runtime. +In our example above, the news-feed component decorates an object of exported properties onto dashboard as **newsFeed**. This allows the +dashboard component to access the $scope of its child at runtime (post construction). The expose feature is very useful when building complex interaction models between components. It adds another dimension to how developers can structure their code while still decoupling concerns. Out-of-the-box angularjs architecture supports child to parent $scope access, but not the other way around. Wilson adds this functionality knowing that there are times when this may be necessary to achieve a desirable solution. +> NOTE: Legacy support for the expose attribute decorates the entire child $scope onto the parent component $scope. This +> functionality is now deprecated as of wilson v4. Please use the **exports** object to itemize exposed functionality +> as this is more explicit and therefore considered best practice. + ## Dependency hooks -Component controllers provide special hooks to optimize the loading of external scriptDependencies. Many times +Wilson components provide special hooks to optimize the loading of external scriptDependencies. Many times a component may need to use a special javascript library to provide its functionality. However, we may not want to add this library to the core application javascript and increase our load time...Enter wilson dependency hooks. @@ -628,15 +507,14 @@ wilson.component('dashboard', { 'https://cdnjs.cloudflare.com/ajax/libs/d3/4.8.0/d3.min.js' ], controller: ['$scope', '$window', function($scope, $window) { - var controller = this; $scope.showCharts = false; - controller.onDependenciesReady = function() { // Fires when dependency scripts are loaded and ready + $scope.onDependenciesReady = function() { // Fires when dependency scripts are loaded and ready $scope.showCharts = true; }; - controller.onDependenciesError = function() { // Fires if dependency scripts fail to load + $scope.onDependenciesError = function() { // Fires if dependency scripts fail to load $window.alert('Sorry we don\'t have what we need to load'); }; @@ -644,7 +522,7 @@ wilson.component('dashboard', { }); ``` If scriptDependencies are defined and non-empty, wilson will attempt to load the scripts when the component is instantiated. The -controller may then implement the **onDependenciesReady** and **onDependenciesError** methods in order to handle the +$scope may then implement the **onDependenciesReady** and **onDependenciesError** methods in order to handle the hooks fired by wilson. > NOTE: Template content that requires the use of scriptDependencies should be manually prevented from rendering prior From b6943a7518bc574b0eea54c13b0bece868f479fb Mon Sep 17 00:00:00 2001 From: Hunter Novak Date: Tue, 29 Aug 2017 14:33:31 -0700 Subject: [PATCH 03/13] Updated routing section to wilson v4. --- concepts/routing/routing.md | 72 +++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/concepts/routing/routing.md b/concepts/routing/routing.md index 9c31551..de6d4bb 100644 --- a/concepts/routing/routing.md +++ b/concepts/routing/routing.md @@ -4,7 +4,7 @@ Routing is a key area where wilson provides extended functionality to angular ap defined from a URL path to a controller and a template/templateUrl. This requires that all templates and controllers be declared on angular prior to routing. With wilson, routes are defined from a url path to a wilson component (angularjs element-style directive). At routing time, wilson determines all necessary dependencies needed to fulfill -the route, loads all javascript and markup templates and then resolves the route and renders the routed component. +the route, loads all javascript, markup templates and styles then resolves the route and renders the routed component. This gives wilson applications the ability to "code-split" their javascript and markup templates. Although the application is a SPA, it does not need to load a monolithic javascript payload that contains the entire application. Rather, as the user navigates @@ -28,9 +28,23 @@ Example routing.json { "routes": [ { - "path": "/", - "component": "home", - "title": "Home Page", + "path": "/", + "component": "home", + "title": "Home Page", + "options": {} + }, + { + "path": "/dashboard/:tabId", + "component": "dashboard", + "title": "Dashboard Page", + "preload": true, + "options": {} + }, + { + "path": "/dashboard/news", + "component": "dashboard", + "title": "Dashboard News Feed", + "defaultParams": { "tabId": "news" }, "options": {} }, { @@ -50,14 +64,16 @@ a null route in the config or if the null route is not the final route entry. # Route Entries -Each route entry has 4 distinct properties: +Each route entry supports the following distinct properties: | Property | Type | Description | | ---------------- |:--------:| -------------------- | -| **path** | string | The URL path, see angularjs [$routeProvider.when()](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider#when) | -| **component** | string | The name of the target component for this route | -| **title** | string | The html title to use for this page (i.e. ...) | -| **options** | Object | An object with optional data used to provide extra functionality | +| **path** | string | The URL path, see angularjs [$routeProvider.when()](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider#when) | +| **component** | string | The name of the target component for this route | +| **title** | string | The html title to use for this page (i.e. ...) | +| **preload** | boolean | Whether or not this route content should be pre-loaded after first navigation | +| **defaultParams** | Object | An object containing default route parameters that should be applied | +| **options** | Object | An object with optional data used to provide extra functionality | These are the basic properties that wilson reads and uses from the route entries. Without adding any option support, an @@ -65,18 +81,27 @@ application can perform simple routing from page to page with changing titles. > Note that **title** may be templated with dynamic content using the [translateTitle()](#translateTitle) method, covered below. +The **preload** property allows designated route content to be pre-loaded in order to improve user experience. If preload is enabled for a +route, it's content will be fetched after the first $locationChangeSuccess event is fired when the app is loaded. All component js, markup +and styles will be loaded silently loaded behind the scenes so that when those routes are eventually navigated to they will already +be cached and can be fulfilled immediately. + The **options** property provides a blank canvas for applications to build intricate routing functionality. Using these properties in conjunction with the IRouteService interface, developers can create new routing constructs as they desire. -# IRouteService +# Implementing a custom router -Every wilson application is required to implement a special service called IRouteService. This service is used at specific +Wilson applications may implement a custom router to handle special routing functionality. The router is a service that is used at specific points during wilson routing to determine how/when to proceed with route fulfillment. This allows the application to control things like restricted routes, path forwarding, dependency resolution, session-based redirections and much more. -IRouteService has access to all route information including the options and data for the current route, this allows distinctive +The custom router service has access to all route information including the options and data for the current route, this allows distinctive configuration per-route that allows for intelligent handling. +Creating a custom router is as easy as configuring it's location in [wilson-config.json](../wilson/core.md#wilson-config) and then declaring it using **wilson.router**. The +default configured location is **/client/src/router.js**. The router definition is effectively the same as a service definition with the only +difference being that there is no service name needed for the router. + Example route entry with options: ```json { @@ -97,9 +122,9 @@ Note the **loggedOutRedirect** options property. Let's assume this property shou redirect a user without a session to "/login". This functionality can easily be implemented via IRouteService's [handleRouteChange()](#handleRouteChange) method. -Example handling in IRouteService: +Example handling in a custom router: ```js -wilson.service('IRouteService', ['$q', '$location', 'AuthService', +wilson.router(['$q', '$location', 'AuthService', function($q, $location, AuthService) { function handleRouteInfo(currentRoute, routeOptions, routeInfo) { @@ -121,19 +146,20 @@ wilson.service('IRouteService', ['$q', '$location', 'AuthService', ``` As you can see in the example, the **handleRouteChange** method has access to routeOptions (the options object -from the current route). IRouteService can inject other application services and use custom logic to support +from the current route). The custom router can inject other application services and use custom logic to support any number of specialized functionalities like the one above. -# IRouteService Required Functions +# Custom Router Interface * [handleRouteChange](#handleRouteChange) * [loadDependencies](#loadDependencies) * [loadSession](#loadSession) * [getTitleText](#getTitleText) -> Note that the examples below implement an IRouteService that has only the sample method. When -> implementing an actual IRouteService, all of the methods below MUST be included on the service. +> NOTE: A custom router acts as an extension of the default router and may implement one +> or more of the above interface methods. Interface methods not included in the custom router +> will inherit the default functionality. ## handleRouteChange(currentRoute, routeOptions, routeInfo) @@ -152,7 +178,7 @@ function handleRouteChange(currentRoute: string, routeOptions: Object, routeInfo ``` Implementation Example: ```js -wilson.service('IRouteService', ['$q', '$location', +wilson.router(['$q', '$location', function($q, $location) { function handleRouteInfo(currentRoute, routeOptions, routeInfo) { @@ -188,7 +214,7 @@ function loadDependencies(routeInfo: Object): Promise; ``` Implementation Example: ```js -wilson.service('IRouteService', ['$q', +wilson.router(['$q', function($q) { function loadDependencies(routeInfo) { @@ -223,7 +249,7 @@ function loadSession(): Promise; ``` Implementation Example: ```js -wilson.service('IRouteService', ['$q', 'AuthService', +wilson.router(['$q', 'AuthService', function($q, AuthService) { function loadSession() { @@ -254,7 +280,7 @@ function getTitleText(routeTitle: string): string; ``` Implementation Example (Basic): ```js -wilson.service('IRouteService', [ +wilson.router([ function() { function getTitleText(routeTitle) { @@ -268,7 +294,7 @@ wilson.service('IRouteService', [ ``` Implementation Example (Advanced): ```js -wilson.service('IRouteService', ['$route', +wilson.router(['$route', function($route) { function getTitleText(routeTitle) { From ebaa013ba5f0d57e6a98c06e651c426d2d0584d0 Mon Sep 17 00:00:00 2001 From: Hunter Novak Date: Tue, 29 Aug 2017 15:12:19 -0700 Subject: [PATCH 04/13] Updated core section to wilson v4 --- concepts/wilson/core.md | 93 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 86 insertions(+), 7 deletions(-) diff --git a/concepts/wilson/core.md b/concepts/wilson/core.md index f6ab02f..024df52 100644 --- a/concepts/wilson/core.md +++ b/concepts/wilson/core.md @@ -19,6 +19,9 @@ Wilson Interface * [getActivePage](#getActivePage) * [getActiveComponent](#getActiveComponent) * [getActiveComponentList](#getActiveComponentList) +* [findComponentId](#findComponentId) +* [destroyComponent](#destroyComponent) +* [router](#router) * [component](#component) * [behavior](#behavior) * [service](#service) @@ -64,8 +67,7 @@ function getActivePage(): string; ## getActiveComponent(componentId) -Return relevant object references and information for a given active wilsonComponentId. The returned -object contains a stored reference to $scope and controller for the given wilsonComponentId. This is useful +Return the component $scope for a given active component instance id (wilsonComponentId). This is useful for tying $element references back to our components without needing to use angularjs's [$compileProvider.debugInfoEnabled](https://docs.angularjs.org/guide/production) option. ```typescript @@ -77,11 +79,10 @@ Usage Example: function someHandler() { var componentId = $('.ht-my-component').data('wilsonComponentId'); - var component = wilson.getActiveComponent(componentId); + var scope = wilson.getActiveComponent(componentId); - console.log(component.name); // --> The simple name of our component "my-component" - console.log(component.scope); // --> The isolateScope instance for this component - console.log(component.controller); // --> The controller instance for this component + console.log(scope); // --> The isolateScope instance for this component + console.log(componentId === scope.component.id); // --> This should always be true } ``` @@ -89,13 +90,89 @@ function someHandler() { ## getActiveComponentList() -Returns a list of all active component objects on wilson. +Returns a list of all active component $scopes on wilson. ```typescript function getActiveComponentList(): Object[]; ``` +## findComponentId(jqElement) + +Find the component that is nearest to the given jqElement and return its instance id. This method traverses up the +DOM tree to the parent to find the component, returning null if not found. + +```typescript +function findComponentId(jqElement: Array): string; +``` +Usage Example: +```js +// Assume we've have an instance of a component with a full name of 'ht-my-component' in the DOM + +function someHandler() { + var someChildElement = $('.ht-my-component div.something'); + var componentId = wilson.findComponentId(someChildElement); + var scope = wilson.getActiveComponent(componentId); + + console.log(scope); // --> The isolateScope instance for the "my-component" component + console.log(scope.component.name); // --> my-component + console.log(componentId === scope.component.id); // --> This should always be true +} + +``` + + +## destroyComponent(componentId) + +Forcibly destroy an active wilson component with the given instance id (componentId). + +```typescript +function destroyComponent(componentId: string): void; +``` +Usage Example: +```js +// Assume we've have an instance of a component with a full name of 'ht-my-component' in the DOM + +function someHandler() { + var componentId = $('.ht-my-component').data('wilsonComponentId'); + var scope = wilson.getActiveComponent(componentId); + + console.log(scope); // --> The isolateScope instance for the "my-component" component + console.log(scope.component.name); // --> my-component + console.log(componentId === scope.component.id); // --> This should always be true + + wilson.destroyComponent(componentId); + + console.log(scope.$$destroyed); // --> This is now true (scope is destroyed) +} + +``` + + +## router(definition) + +Declare a [custom router service](../routing/routing.md#Implementingacustomrouter) on the wilson app module. The definition is exactly the same as if it +was declared as a factory-style service on angularjs directly (sans the name parameter). See the angularjs documentation for [$provide.factory](https://docs.angularjs.org/api/auto/service/$provide#factory). + +```typescript +function router(definition: any[]|Function): void; +``` +Usage Example: +```js +wilson.router(['$q', + function($q) { + + function handleRouteInfo(currentRoute, routeOptions, routeInfo) { + return $q.when(); + } + + // Return service + return { handleRouteInfo: handleRouteInfo }; + } +]); +``` + + ## component(name, config) Declare a new component onto the wilson app module. This method is a wrapper for declaring a @@ -231,6 +308,8 @@ Example Config: "name": "MyApplication", "version": "1.0.0", "connectionFilters": "EYJwhgdgJgvAzgBzAYwKZwD6gPYHc6ogzIAWI2AtqhlKgG4CWaMFKGANpAOYCuYXqGKggYEnAC4AzbCAoxacANbjsCIA" + "assetPath": "/client", + "useVersionedAssets": true }, "routes": [ { From 11c8544ea47d7bdcff14a1a33176dce5e3185071 Mon Sep 17 00:00:00 2001 From: Hunter Novak Date: Tue, 29 Aug 2017 17:03:57 -0700 Subject: [PATCH 05/13] More updates to the core section. --- concepts/wilson/core.md | 51 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/concepts/wilson/core.md b/concepts/wilson/core.md index 024df52..43e1ed0 100644 --- a/concepts/wilson/core.md +++ b/concepts/wilson/core.md @@ -21,6 +21,7 @@ Wilson Interface * [getActiveComponentList](#getActiveComponentList) * [findComponentId](#findComponentId) * [destroyComponent](#destroyComponent) +* [routeInfo](#routeInfo) * [router](#router) * [component](#component) * [behavior](#behavior) @@ -138,7 +139,7 @@ function someHandler() { var scope = wilson.getActiveComponent(componentId); console.log(scope); // --> The isolateScope instance for the "my-component" component - console.log(scope.component.name); // --> my-component + console.log(scope.component.name); // --> "my-component" console.log(componentId === scope.component.id); // --> This should always be true wilson.destroyComponent(componentId); @@ -149,6 +150,54 @@ function someHandler() { ``` +## routeInfo + +An object representing the route information for the currently active route. This can be used from components to + determine any data parameters that are represented in the route information. + +```typescript +routeInfo: Object; +``` + +Given the following routing.json: +```json +{ + "routes": [ + { + "path": "/dashboard/:tabId", + "component": "dashboard", + "title": "Dashboard Page", + "preload": true, + "options": {} + }, + { + "path": null, + "component": "404", + "title": "Not Found", + "options": {} + } + ] +} +``` + +Let's say we've just routed to the "/dashboard/newsfeed" and the "dashboard" component constructor is called. The following +dashboard component implementation shows how the route parameters can be accessed via wilson.routeInfo: + +```js +wilson.component('dashboard', { + controller: ['$scope', '$element', function($scope, $element) { + + console.log(wilson.routeInfo.tabId); // --> "newsfeed" -- Routing data is accessible here via the routeInfo object on wilson + + }] +}); +``` + +> NOTE: The routeInfo object is a virtual property and represents a copy of the currently active routeInfo. This +> object is immutable and cannot be changed by its accessor. **IMPORTANT:** This means if wilson.routeInfo is stored into a local +> variable it will not update on route change. + + ## router(definition) Declare a [custom router service](../routing/routing.md#Implementingacustomrouter) on the wilson app module. The definition is exactly the same as if it From ef622dfc414a30032b4d522e65924a962cc03f1b Mon Sep 17 00:00:00 2001 From: Hunter Novak Date: Tue, 29 Aug 2017 17:06:32 -0700 Subject: [PATCH 06/13] Updating version in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 41e0f80..f47eac9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Wilson - v3.1.0 +# Wilson - v4.1.2 Wilson is framework that adds a distinct component abstraction to Angularjs web applications. These components can be lazily-loaded at route-time automatically based on dependencies (this works in conjunction with the Wilson From bbf9894dba057881428e0c195664877121140a02 Mon Sep 17 00:00:00 2001 From: Hunter Novak Date: Tue, 29 Aug 2017 17:15:56 -0700 Subject: [PATCH 07/13] Small update --- concepts/routing/routing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/concepts/routing/routing.md b/concepts/routing/routing.md index de6d4bb..5979b12 100644 --- a/concepts/routing/routing.md +++ b/concepts/routing/routing.md @@ -6,7 +6,7 @@ and controllers be declared on angular prior to routing. With wilson, routes are component (angularjs element-style directive). At routing time, wilson determines all necessary dependencies needed to fulfill the route, loads all javascript, markup templates and styles then resolves the route and renders the routed component. -This gives wilson applications the ability to "code-split" their javascript and markup templates. Although the application +This gives wilson applications the ability to "code-split" their javascript, markup templates and styles. Although the application is a SPA, it does not need to load a monolithic javascript payload that contains the entire application. Rather, as the user navigates to different pages, new javascript is added to support the new areas. This greatly reduces the payload size of javascript needed to initially load the application and removes development concern as a codebase grows larger and larger over time. From 482e01775b49725459486c10968475228be043ce Mon Sep 17 00:00:00 2001 From: Hunter Novak Date: Tue, 29 Aug 2017 17:22:03 -0700 Subject: [PATCH 08/13] Routing param update --- concepts/routing/routing.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/concepts/routing/routing.md b/concepts/routing/routing.md index 5979b12..3c1c387 100644 --- a/concepts/routing/routing.md +++ b/concepts/routing/routing.md @@ -71,12 +71,12 @@ Each route entry supports the following distinct properties: | **path** | string | The URL path, see angularjs [$routeProvider.when()](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider#when) | | **component** | string | The name of the target component for this route | | **title** | string | The html title to use for this page (i.e. ...) | -| **preload** | boolean | Whether or not this route content should be pre-loaded after first navigation | -| **defaultParams** | Object | An object containing default route parameters that should be applied | +| **preload** | boolean | A flag to specify if the contents of this route should be pre-loaded - Optional | +| **defaultParams** | Object | An object containing default route parameters that should be applied - Optional | | **options** | Object | An object with optional data used to provide extra functionality | -These are the basic properties that wilson reads and uses from the route entries. Without adding any option support, an +These are the properties that wilson reads and uses from the route entries. Without adding any option support, an application can perform simple routing from page to page with changing titles. > Note that **title** may be templated with dynamic content using the [translateTitle()](#translateTitle) method, covered below. From b7a638616726252257cc62db05352e4a7b0380f4 Mon Sep 17 00:00:00 2001 From: Hunter Novak Date: Tue, 29 Aug 2017 17:33:50 -0700 Subject: [PATCH 09/13] Some corrections --- concepts/routing/routing.md | 12 ++++++------ concepts/wilson/core.md | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/concepts/routing/routing.md b/concepts/routing/routing.md index 3c1c387..522cae7 100644 --- a/concepts/routing/routing.md +++ b/concepts/routing/routing.md @@ -83,11 +83,11 @@ application can perform simple routing from page to page with changing titles. The **preload** property allows designated route content to be pre-loaded in order to improve user experience. If preload is enabled for a route, it's content will be fetched after the first $locationChangeSuccess event is fired when the app is loaded. All component js, markup -and styles will be loaded silently loaded behind the scenes so that when those routes are eventually navigated to they will already +and styles will be loaded silently behind the scenes so that when those routes are eventually navigated to they will already be cached and can be fulfilled immediately. The **options** property provides a blank canvas for applications to build intricate routing functionality. Using these -properties in conjunction with the IRouteService interface, developers can create new routing constructs as they desire. +properties in conjunction with a custom router, developers can create new routing constructs as they desire. # Implementing a custom router @@ -98,9 +98,9 @@ things like restricted routes, path forwarding, dependency resolution, session-b The custom router service has access to all route information including the options and data for the current route, this allows distinctive configuration per-route that allows for intelligent handling. -Creating a custom router is as easy as configuring it's location in [wilson-config.json](../wilson/core.md#wilson-config) and then declaring it using **wilson.router**. The -default configured location is **/client/src/router.js**. The router definition is effectively the same as a service definition with the only -difference being that there is no service name needed for the router. +Creating a custom router is as easy as configuring it's location in [wilson-config.json](../wilson/core.md#wilson-config) and then declaring it using **wilson.router**. The router +file is specified via the **server.projectPaths.routeService** config property and defaults to a value of **/client/src/router.js**. The router definition is effectively the same as a service definition +with the only difference being that there is no service name needed for the router. Example route entry with options: ```json @@ -158,7 +158,7 @@ any number of specialized functionalities like the one above. * [getTitleText](#getTitleText) > NOTE: A custom router acts as an extension of the default router and may implement one -> or more of the above interface methods. Interface methods not included in the custom router +> or more of the above interface methods. Any methods not included in the custom router > will inherit the default functionality. ## handleRouteChange(currentRoute, routeOptions, routeInfo) diff --git a/concepts/wilson/core.md b/concepts/wilson/core.md index 43e1ed0..82b92e0 100644 --- a/concepts/wilson/core.md +++ b/concepts/wilson/core.md @@ -200,7 +200,7 @@ wilson.component('dashboard', { ## router(definition) -Declare a [custom router service](../routing/routing.md#Implementingacustomrouter) on the wilson app module. The definition is exactly the same as if it +Declare a [custom router service](../routing/routing.md#implementing-a-custom-router) on the wilson app module. The definition is exactly the same as if it was declared as a factory-style service on angularjs directly (sans the name parameter). See the angularjs documentation for [$provide.factory](https://docs.angularjs.org/api/auto/service/$provide#factory). ```typescript From 94bf6458a5175a8bf14f69c52ae5250335dcff10 Mon Sep 17 00:00:00 2001 From: Hunter Novak Date: Tue, 29 Aug 2017 17:37:02 -0700 Subject: [PATCH 10/13] More updates --- concepts/wilson/core.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/concepts/wilson/core.md b/concepts/wilson/core.md index 82b92e0..78c4d07 100644 --- a/concepts/wilson/core.md +++ b/concepts/wilson/core.md @@ -187,15 +187,17 @@ dashboard component implementation shows how the route parameters can be accesse wilson.component('dashboard', { controller: ['$scope', '$element', function($scope, $element) { - console.log(wilson.routeInfo.tabId); // --> "newsfeed" -- Routing data is accessible here via the routeInfo object on wilson + console.log(wilson.routeInfo.tabId); // --> "newsfeed" -- Routing data is accessible here via the routeInfo object on wilson + + $scope.currentTab = wilson.routeInfo.tabId; // E.G. Use routeInfo data to determine the state of the component }] }); ``` > NOTE: The routeInfo object is a virtual property and represents a copy of the currently active routeInfo. This -> object is immutable and cannot be changed by its accessor. **IMPORTANT:** This means if wilson.routeInfo is stored into a local -> variable it will not update on route change. +> object is immutable and cannot be changed by its accessor. **IMPORTANT: This means if wilson.routeInfo is stored into a local +> variable it will not update on route change.** ## router(definition) From 79e06dfb5eeaa070b1cdd0fb1e7355bdab45dce8 Mon Sep 17 00:00:00 2001 From: Hunter Novak Date: Tue, 29 Aug 2017 17:38:09 -0700 Subject: [PATCH 11/13] Fixed json error. --- concepts/wilson/core.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/concepts/wilson/core.md b/concepts/wilson/core.md index 78c4d07..0ef8228 100644 --- a/concepts/wilson/core.md +++ b/concepts/wilson/core.md @@ -358,7 +358,7 @@ Example Config: "app": { "name": "MyApplication", "version": "1.0.0", - "connectionFilters": "EYJwhgdgJgvAzgBzAYwKZwD6gPYHc6ogzIAWI2AtqhlKgG4CWaMFKGANpAOYCuYXqGKggYEnAC4AzbCAoxacANbjsCIA" + "connectionFilters": "EYJwhgdgJgvAzgBzAYwKZwD6gPYHc6ogzIAWI2AtqhlKgG4CWaMFKGANpAOYCuYXqGKggYEnAC4AzbCAoxacANbjsCIA", "assetPath": "/client", "useVersionedAssets": true }, From 18b1d2e9e5de6dbcba92ff7d2e0cc35666deb2fe Mon Sep 17 00:00:00 2001 From: Hunter Novak Date: Tue, 29 Aug 2017 17:43:21 -0700 Subject: [PATCH 12/13] Component update fixes. --- concepts/components/components.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/concepts/components/components.md b/concepts/components/components.md index de15b85..c4e89e7 100644 --- a/concepts/components/components.md +++ b/concepts/components/components.md @@ -291,7 +291,7 @@ controlled by the stateMachine object itself. Example stateMachine definition: ```js -controller.setState({ +$scope.stateMachine({ initial: 'Loading', events: [ { name: 'loaded', from: 'Loading', to: 'Ready' }, @@ -302,7 +302,7 @@ controller.setState({ { state: 'Failed', duration: 3000, timeoutEvent: 'retry', refreshEvent: 'failed' } ], callbacks: {} -}) +}); ``` Each timeout entry supports 4 properties: @@ -321,7 +321,7 @@ Wilson component scopes are decorated with special storage helper methods for se is specific to the component itself. This data is stored to a component-namespaced key that isolates the values stored from other components. These values should be explicitly set and cleared from the component scope. -## $scope.storage.get(key, defaultValue) +## $scope.storage.get(key, defaultValue) Retrieve a value from this component's localStorage namespace at a given key. If the value does not exist return the specified defaultValue, otherwise return null. @@ -348,7 +348,7 @@ wilson.component('dashboard', { }); ``` -## $scope.storage.set(key, value) +## $scope.storage.set(key, value) Store a value to this component's localStorage namespace at a given key. This will persist in the browser indefinitely and will be retained when the browser is refreshed or even closed. @@ -379,7 +379,7 @@ These methods provide the same functionality as the original handling methods, b the scope of the component is destroy. This allows developers to use them freely without having to worry about memory/reference management. -## $scope.on.event(eventName, handler) +## $scope.on.event(eventName, handler) Alias for $scope.$on. See [angularjs documentation](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on). @@ -387,7 +387,7 @@ Alias for $scope.$on. See [angularjs documentation](https://docs.angularjs.org/a function event(eventName: string, handler: Function): void; ``` -## $scope.on.watch(key, handler) +## $scope.on.watch(key, handler) Alias for $scope.$watch. See [angularjs documentation](https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watch). @@ -395,7 +395,7 @@ Alias for $scope.$watch. See [angularjs documentation](https://docs.angularjs.or function watch(key: string, handler: Function): void; ``` -## $scope.on.signal(signal, handler) +## $scope.on.signal(signal, handler) Alias for signal.add. See [js-signal documentation](http://millermedeiros.github.io/js-signals/docs/symbols/Signal.html#add). @@ -405,7 +405,7 @@ function signal(signal: Signal, handler: Function): void; > EXPLAINED: This method attaches the **handler** to the **signal** by calling the signal.add. -## $scope.on.digest(handler) +## $scope.on.digest(handler) Run the given handler after each digest cycle completes. @@ -413,7 +413,7 @@ Run the given handler after each digest cycle completes. function digest(handler: Function): void; ``` -## $scope.on.pageUnload(handler, includeLocalNav) +## $scope.on.pageUnload(handler, includeLocalNav) Run the given handler when the pages is about to unload. If **includeLocalNav** is true, then also run on local page navigation. From 725e4a14db359755112fc832825a823ea4878944 Mon Sep 17 00:00:00 2001 From: Hunter Novak Date: Tue, 29 Aug 2017 17:44:36 -0700 Subject: [PATCH 13/13] Fix typo. --- best-practices.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/best-practices.md b/best-practices.md index b112fcf..7188460 100644 --- a/best-practices.md +++ b/best-practices.md @@ -115,7 +115,7 @@ wilson.service('MyService', ['$rootScope', function($rootScope) { service.doSomethingElse = function doSomethingElse() {}; - service.doALlTheThings = function doAllTheThings() {}; + service.doAllTheThings = function doAllTheThings() {}; return service; }]);