Repository: google/uniflow-polymer Branch: master Commit: dce13b9d10ff Files: 33 Total size: 171.1 KB Directory structure: gitextract_6nfjv9bm/ ├── .bower.json ├── .gitignore ├── CONTRIBUTING ├── LICENSE ├── README.md ├── action-dispatcher.html ├── action-emitter.html ├── all-imports.html ├── analysis.json ├── application-state.html ├── bower.json ├── index.html ├── list-view.html ├── model-view.html ├── state-aware.html ├── state-mutator.html ├── test/ │ ├── action-dispatcher_test.html │ ├── action-emitter_test.html │ ├── application-state_test.html │ ├── list-view_test.html │ ├── model-view_test.html │ └── state-aware_test.html └── todomvc/ ├── README.md ├── elements/ │ ├── todo-action-dispatcher.html │ ├── todo-app.html │ ├── todo-footer.html │ ├── todo-header.html │ ├── todo-item.html │ ├── todo-items.html │ └── todo-styles.html ├── index.html ├── manifest.json └── scripts/ └── actions.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .bower.json ================================================ { "name": "uniflow-polymer", "version": "0.6.0", "authors": [ "Andrei Militeev " ], "description": "A straightforward way to architect Polymer application using unidirectional data flow.", "keywords": [ "web-component", "polymer", "uniflow", "unidirectional", "flow" ], "license": "https://raw.githubusercontent.com/google/uniflow-polymer/master/LICENSE", "homepage": "https://github.com/google/uniflow-polymer/", "ignore": [ "/.*", "/test/" ], "dependencies": { "polymer": "Polymer/polymer#^2.0.0" }, "devDependencies": { "app-route": "PolymerElements/app-route#^2.0.2", "iron-component-page": "PolymerElements/iron-component-page#^3.0.0", "iron-demo-helpers": "PolymerElements/iron-demo-helpers#^2.0.0", "iron-icon": "PolymerElements/iron-icon#^2.0.0", "iron-icons": "PolymerElements/iron-icons#^2.0.0", "iron-test-helpers": "PolymerElements/iron-test-helpers#^2.0.0", "paper-styles": "PolymerElements/paper-styles#^2.0.0", "test-fixture": "PolymerElements/test-fixture#3.0.0-rc.1", "web-component-tester": "^v6.0.0", "todomvc-app-css": "^2.1.0", "iron-localstorage": "PolymerElements/iron-localstorage#^2.0.0" } } ================================================ FILE: .gitignore ================================================ bower_components/ .idea/ ================================================ FILE: CONTRIBUTING ================================================ Want to contribute? Great! First, read this page (including the small print at the end). ### Before you contribute Before we can use your code, you must sign the [Google Individual Contributor License Agreement] (https://cla.developers.google.com/about/google-individual) (CLA), which you can do online. The CLA is necessary mainly because you own the copyright to your changes, even after your contribution becomes part of our codebase, so we need your permission to use and distribute your code. We also need to be sure of various other things—for instance that you'll tell us if you know that your code infringes on other people's patents. You don't have to sign the CLA until after you've submitted your code for review and a member has approved it, but you must do it before we can put your code into our codebase. Before you start working on a larger contribution, you should get in touch with us first through the issue tracker with your idea so that we can help out and possibly guide you. Coordinating up front makes it much easier to avoid frustration later on. ### Code reviews All submissions, including submissions by project members, require review. We use Github pull requests for this purpose. ### The small print Contributions made by corporations are covered by a different agreement than the one above, the [Software Grant and Corporate Contributor License Agreement] (https://cla.developers.google.com/about/google-corporate). ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2016 Google Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ # UniFlow for Polymer 2.x Set of mixins to enable uni-directional data flow in Polymer application. **Important!** *This library was developed as part of internal project at Google and isn't directly affiliated with the Polymer project (although Polymer team has provided some good feedback on UniFlow implementation).* ## History & Overview When you start working on a new Polymer application, it's easy to start and build the first few elements, and make them communicate via events and data binding, so everything looks nice and rosy. However, as the number and complexity of elements grows, it becomes increasingly difficult to manage relationships between them, trace where/when the data changes happened, and debug the problems. So this project started as an attempt by our team at Google to find a good way to architect large Polymer application. Inspired by React's community Flux (and, later, Redux) architecture, we implemented a unidirectional data flow pattern (data down, events up) for Polymer. We found that when using UniFlow application code becomes more streamlined (e.g. it is clear what the responsibilities of each element are) and much easier to manage; the code has fewer bugs, and debugging is a lot more efficient. Adding new functionality no longer exponentially increases complexity. This project was also inspired by Backbone Marionette. Backbone.js back in the days of its glory was a great library that provided a nice set of building blocks for building JavaScript applications. However, it left much of the application design, architecture and scalability to the developer, including memory management, view management, and more. Marionette brought an application architecture to Backbone, along with built in view management and memory management. It was designed to be a lightweight and flexible library of tools that sits on top of Backbone, providing the framework for building a scalable application. Uniflow strives to achieve similar goal for Polymer. We feel that Polymer, and web components in general, is a great concept that takes interoperability and encapsulation in Web development to the next level. But it lacked the patterns for building large and complex applications, and this is the void we expect UniFlow to fill. It is still in beta, so breaking changes may be happening before the first release. However, we believe that abstractions implemented in the library can be useful for Polymer community, so we encourage people to try, fork, ask questions, send comments, and submit pull requests. ## Applicability This library implements the architectural pattern called 'unidirectional data flow'. It works best if application logic involves complicated data management, when multiple elements need to have access to or modify the same data. Even though the pattern can be implemented just using built-in Polymer concepts, such as custom events and data binding, the UniFlow library provides a useful set of tools and abstractions, and helps to structure application code. ## Implementation UniFlow is implemented as a set of mixins that developers apply to their elements. It is assumed that each application has a singleton application element that maintains state of entire application. Each element that needs access to the data is bound, directly or indirectly, to sub-tree of application state tree. Two way data binding is never used to send data up, from child to parent, so only parent elements send data to children using one way data binding. Child elements, in turn, send the events (emit actions) responding to user actions, indicating that the data may need to be modified. Special non-visual elements called action dispatchers mutate the data, then all elements listening to the data changes render new data. # API Documentation ## Action Dispatcher Use UniFlow.ActionDispatcher for non-visual elements that process actions emitted by visual elements. Action dispatchers usually placed at the application level. Each action dispatcher element gets a chance to process the action in the order the elements are present in the DOM tree. It is important that action dispatcher elements get two-way data binding to application state as follows: Action dispatcher elements can include nested action dispatchers, so you can have a hierarchical organization of action dispatchers. ### Example: #### HTML: ```html ``` #### JavaScript: ```javascript class ParentDispatcher extends UniFlow.ActionDispatcher(Polymer.Element) { static get is() { return 'parent-dispatcher'; } MY_ACTION(detail) { // do MY_ACTION processing here // return false if you want to prevent other action dispatchers from // further processing of this action }; } customElements.define(ParentDispatcher.is, ParentDispatcher); ``` ## Action Emitter Whenever element needs to emit an action, this mixin should be used. Action object must always include type property. ## Application State Assign this mixin to your main application element. It provides global state and functionality to maintain individual elements states. This mixin is responsible for notifying all state-aware elements about their state changes (provided those elements have `statePath` property defined). Only one element in the application is supposed to have this mixin. ### Example: #### HTML: ```html ``` #### JavaScript: ```javascript class MyApp extends UniFlow.ApplicationState(Polymer.Element) { static get is() { return 'my-app'; } connectedCallback() { super.connectedCallback(); this.state = { someElement: {} } } } customElements.define(MayApp.is, MyApp); ``` In the example above, `` will receive notification of any changes to the state, as if it was declared as follows: ```html ``` Also, if `` has `propertyA`, on element attach this property will be assigned the value of `state.someElement.propertyA`, and receive all notification of the property change whenever the corresponding data in state tree changes. This essentially translates to following declaration: ```html ``` Note that data binding is one-way in both cases. Although state-aware elements can modify their own state, it is considered their private state and no other elements will be notified of those changes. ## List View This mixin used by elements that need to render multiple models backed by 'list' array. You may want to use ModelView to render individual models in the list. The mixin supports element selection by setting predefined $selected property on list elements. ### Example: #### HTML: ```html
Selected: [[selectedCount]] items Delete ``` #### JavaScript: ```javascript class ListElement extends Polymer.GestureEventListeners(UniFlow.ListView(UniFlow.StateAware(Polymer.Element))) { static get is() { return "list-element"; } onDeleteTap() { this.deleteSelected(); } } customElements.define(ListElement.is, ListElement); ``` In the example above list view element is also state-aware, meaning it has its own place in the application state tree. Assuming it has been declared as follows: ```html ``` it will be rendering `state.listElement.list` and observing changes to it. Each `model-view` within dom-repeat template will have `state-path` property set to `state.listElement.list.#` where `index` is the element's index in the array. ## Model View Element rendering data represented by a single object (model) in the application state should use ModelView mixin. Model View is a powerful concept that encapsulates model data (likely the data received from the server and to be persisted to the server if modified as a result of user actions), status (validity of the data, flag that data was modified, notifications for the user, etc.). Auxiliary data supplied by action dispatchers and needed for display purposes or element's logic should be defined as element’s properties. Same applies to data created/modified by the element but not intended to be persisted. If `StateAware` mixin is used along with `ModelView`, you can take advantage of statePath property that indicates path to the element's state in the application state tree. Whenever any data is mutated by action dispatchers at statePath or below, the element will receive notification of its properties' change (even if there is no explicit binding for those properties). See `UniFlow.StateAware` for more details and example. ModelView mixin defines some properties that are intended to be overridden in the elements: + `validation` property allows to specify validation rules that will be applied when validateModel() method is called. As a result of this method validation status will be updated to indicate result for each model field that has validation rule associated with it. + `saveAction` property indicates which action should be emitted when saveModel method is called to perform save of the model. + `getMessage` should be overridden with the function returning message string for given error code (to translate validation error code to message) ### Example: #### HTML: ```html ``` #### JavaScript: ```javascript class MyModel extends Polymer.GestureEventListeners(UniFlow.ModelView(Polymer.Element)) { static get is() { return "my-model"; } get saveAction() { return 'MY_SAVE'; } get validation() { return { name: (value) => { if (!value || !value.trim()) { return 'Name is not specified'; } } } } connectedCallback() { super.connectedCallback(); this.fetchData(); }, fetchData() { this.emitAction({ type: 'MY_FETCH', path: 'model' }); }, onSaveTap() { this.validateAndSave(); } } customElements.define(MyModel.is, MyModel); ``` In the example above model view has input field for `name` property and Save button. On element attach the action is emitted to fetch the model's data. Note that in `emitAction()` method the path is specified as `'model'`. ActionEmitter mixin is responsible of expanding the path with element's state path, ensuring that when action dispatcher gets to process the action, the path contains full path in the state tree. So assuming that `my-model` is declared as follows: ```html ``` the path in `MY_FETCH` action gets expanded to `state.myModel.model`. `validation` property is an object that contains methods for fields validation. The keys in this object should match model field names, the values are validation methods. Method receives current value of the field and should return non-falsy value (string or error code) if the value of the field didn't pass validation. `status.validation` object will be populated with the results of validation with the keys matching field names and values being objects containing two fields: - `invalid`: true when the value is not valid - `errorMessage`: the message to show to user So in the example above if user clicks on Save button with name not entered, they will get 'Name is not specified' error message on the input element. When the name is non-empty, validation will pass and `MY_SAVE` action will be emitted with model passed as a parameter and `'model'` as path. ## State Aware Key mixin that must be assigned to all elements that need to access application state and/or have access to the application element. The element is notified of any changes to application's state, as well as all its properties when they're modified by state mutator elements. `state-path` property must be used to identify path to element's state in application state tree. ### Example: #### HTML: ```html ``` #### JavaScript: ```javascript class MyElement extends UniFlow.StateAware(Polymer.Element) { static get is() { return 'my-element'; } properties: { valueB: String } } customElements.define(MyElement.is, MyElement); ``` When above element is declared as follows: ```html ``` it will be notified about changes (and render those) to `state.valueA` or `state.myElement.valueB` in action dispatchers or other state mutating elements. ## State Mutator Some non-visual elements, like action dispatchers, need to modify application state, in which case they should have this mixin assigned. Implements state- aware and re-declares state property with notify attribute. State mutator elements are only supposed to exist at the application level. ================================================ FILE: action-dispatcher.html ================================================ ================================================ FILE: action-emitter.html ================================================ ================================================ FILE: all-imports.html ================================================ ================================================ FILE: analysis.json ================================================ { "schema_version": "1.0.0", "mixins": [ { "description": " Key mixin that must be assigned to all elements that need to access\n application state and/or have access to the application element. The element is\n notified of any changes to application's state, as well as all its properties\n when they're modified by state mutator elements. `state-path` property must\n be used to identify path to element's state in application state tree. \n\n ### Example:\n\n #### HTML:\n\n \n\n #### JavaScript:\n\n class MyElement extends UniFlow.StateAware(Polymer.Element) {\n static get is() { return 'my-element'; }\n\n static get properties() {\n return {\n valueB: String\n }\n }\n }\n\n customElement.define(MyElement.is, MyElement);\n\n When above element is declared as follows:\n\n \n\n it will be notified about changes (and render those) to `state.valueA` or\n `state.myElement.valueB` in action dispatchers or other state mutating\n elements.\n\n ", "summary": "", "path": "state-aware.html", "properties": [ { "name": "state", "type": "Object", "description": "Application state, shared among application and all state-aware elements.\nThis property is initialized when element is attached.", "privacy": "public", "sourceRange": { "start": { "line": 74, "column": 10 }, "end": { "line": 76, "column": 11 } }, "metadata": { "polymer": {} } }, { "name": "statePath", "type": "string", "description": "Path to element state in the application state tree.", "privacy": "public", "sourceRange": { "start": { "line": 81, "column": 10 }, "end": { "line": 83, "column": 11 } }, "metadata": { "polymer": {} } }, { "name": "stateAware", "type": "boolean", "description": "", "privacy": "public", "sourceRange": { "start": { "line": 85, "column": 10 }, "end": { "line": 89, "column": 11 } }, "metadata": { "polymer": {} }, "defaultValue": "true" }, { "name": "application", "type": "Object", "description": "Application-level object that allows all state-aware objects access\nto application element. This property is shared among all state-aware\nelements and has element field initialized with reference to application\nelement. Any state-aware element can access application element using\n`getApplication()` method. Also, all state-aware elements\nadd themselves to `application.stateAwareElements` array on attach (and\nremove on detach); this list is used to send notification about\nelement state changes.", "privacy": "public", "sourceRange": { "start": { "line": 101, "column": 10 }, "end": { "line": 107, "column": 11 } }, "metadata": { "polymer": {} } } ], "methods": [ { "name": "connectedCallback", "description": "Adds this element to the list of state-aware elements in the application.\nSets the value of state property to the state of the application element.", "privacy": "public", "sourceRange": { "start": { "line": 116, "column": 6 }, "end": { "line": 132, "column": 7 } }, "metadata": {}, "params": [] }, { "name": "disconnectedCallback", "description": "Removes this element from the list of state-aware elements in the\napplication.", "privacy": "public", "sourceRange": { "start": { "line": 138, "column": 6 }, "end": { "line": 145, "column": 7 } }, "metadata": {}, "params": [] }, { "name": "getApplication", "description": "Returns application element.", "privacy": "public", "sourceRange": { "start": { "line": 151, "column": 6 }, "end": { "line": 153, "column": 7 } }, "metadata": {}, "params": [], "return": { "type": "Element" } } ], "staticMethods": [], "demos": [], "metadata": {}, "sourceRange": { "start": { "line": 65, "column": 2 }, "end": { "line": 155, "column": 6 } }, "privacy": "public", "name": "UniFlow.StateAware", "attributes": [ { "name": "state", "description": "Application state, shared among application and all state-aware elements.\nThis property is initialized when element is attached.", "sourceRange": { "start": { "line": 74, "column": 10 }, "end": { "line": 76, "column": 11 } }, "metadata": {}, "type": "Object" }, { "name": "state-path", "description": "Path to element state in the application state tree.", "sourceRange": { "start": { "line": 81, "column": 10 }, "end": { "line": 83, "column": 11 } }, "metadata": {}, "type": "string" }, { "name": "state-aware", "description": "", "sourceRange": { "start": { "line": 85, "column": 10 }, "end": { "line": 89, "column": 11 } }, "metadata": {}, "type": "boolean" }, { "name": "application", "description": "Application-level object that allows all state-aware objects access\nto application element. This property is shared among all state-aware\nelements and has element field initialized with reference to application\nelement. Any state-aware element can access application element using\n`getApplication()` method. Also, all state-aware elements\nadd themselves to `application.stateAwareElements` array on attach (and\nremove on detach); this list is used to send notification about\nelement state changes.", "sourceRange": { "start": { "line": 101, "column": 10 }, "end": { "line": 107, "column": 11 } }, "metadata": {}, "type": "Object" } ], "events": [], "styling": { "cssVariables": [], "selectors": [] }, "slots": [] }, { "description": " Some non-visual elements, like action dispatchers, need to modify application\n state, in which case they should have this mixin applied. Implements state-\n aware and re-declares state property with notify attribute. State mutator elements\n are only supposed to exist at the application level.\n\n ", "summary": "", "path": "state-mutator.html", "properties": [ { "name": "state", "type": "Object", "description": "Application state.", "privacy": "public", "sourceRange": { "start": { "line": 41, "column": 10 }, "end": { "line": 44, "column": 11 } }, "metadata": { "polymer": { "notify": true } } }, { "name": "statePath", "type": "string", "description": "Path to element state in the application state tree.", "privacy": "public", "sourceRange": { "file": "state-aware.html", "start": { "line": 81, "column": 10 }, "end": { "line": 83, "column": 11 } }, "metadata": { "polymer": {} }, "inheritedFrom": "UniFlow.StateAware" }, { "name": "stateAware", "type": "boolean", "description": "", "privacy": "public", "sourceRange": { "file": "state-aware.html", "start": { "line": 85, "column": 10 }, "end": { "line": 89, "column": 11 } }, "metadata": { "polymer": {} }, "defaultValue": "true", "inheritedFrom": "UniFlow.StateAware" }, { "name": "application", "type": "Object", "description": "Application-level object that allows all state-aware objects access\nto application element. This property is shared among all state-aware\nelements and has element field initialized with reference to application\nelement. Any state-aware element can access application element using\n`getApplication()` method. Also, all state-aware elements\nadd themselves to `application.stateAwareElements` array on attach (and\nremove on detach); this list is used to send notification about\nelement state changes.", "privacy": "public", "sourceRange": { "file": "state-aware.html", "start": { "line": 101, "column": 10 }, "end": { "line": 107, "column": 11 } }, "metadata": { "polymer": {} }, "inheritedFrom": "UniFlow.StateAware" } ], "methods": [ { "name": "connectedCallback", "description": "Adds this element to the list of state-aware elements in the application.\nSets the value of state property to the state of the application element.", "privacy": "public", "sourceRange": { "file": "state-aware.html", "start": { "line": 116, "column": 6 }, "end": { "line": 132, "column": 7 } }, "metadata": {}, "params": [], "inheritedFrom": "UniFlow.StateAware" }, { "name": "disconnectedCallback", "description": "Removes this element from the list of state-aware elements in the\napplication.", "privacy": "public", "sourceRange": { "file": "state-aware.html", "start": { "line": 138, "column": 6 }, "end": { "line": 145, "column": 7 } }, "metadata": {}, "params": [], "inheritedFrom": "UniFlow.StateAware" }, { "name": "getApplication", "description": "Returns application element.", "privacy": "public", "sourceRange": { "file": "state-aware.html", "start": { "line": 151, "column": 6 }, "end": { "line": 153, "column": 7 } }, "metadata": {}, "params": [], "return": { "type": "Element" }, "inheritedFrom": "UniFlow.StateAware" } ], "staticMethods": [], "demos": [], "metadata": {}, "sourceRange": { "start": { "line": 33, "column": 2 }, "end": { "line": 48, "column": 6 } }, "privacy": "public", "name": "UniFlow.StateMutator", "attributes": [ { "name": "state", "description": "Application state.", "sourceRange": { "start": { "line": 41, "column": 10 }, "end": { "line": 44, "column": 11 } }, "metadata": {}, "type": "Object" }, { "name": "state-path", "description": "Path to element state in the application state tree.", "sourceRange": { "file": "state-aware.html", "start": { "line": 81, "column": 10 }, "end": { "line": 83, "column": 11 } }, "metadata": {}, "type": "string", "inheritedFrom": "UniFlow.StateAware" }, { "name": "state-aware", "description": "", "sourceRange": { "file": "state-aware.html", "start": { "line": 85, "column": 10 }, "end": { "line": 89, "column": 11 } }, "metadata": {}, "type": "boolean", "inheritedFrom": "UniFlow.StateAware" }, { "name": "application", "description": "Application-level object that allows all state-aware objects access\nto application element. This property is shared among all state-aware\nelements and has element field initialized with reference to application\nelement. Any state-aware element can access application element using\n`getApplication()` method. Also, all state-aware elements\nadd themselves to `application.stateAwareElements` array on attach (and\nremove on detach); this list is used to send notification about\nelement state changes.", "sourceRange": { "file": "state-aware.html", "start": { "line": 101, "column": 10 }, "end": { "line": 107, "column": 11 } }, "metadata": {}, "type": "Object", "inheritedFrom": "UniFlow.StateAware" } ], "events": [], "styling": { "cssVariables": [], "selectors": [] }, "slots": [], "mixins": [ "UniFlow.StateAware" ] }, { "description": " Use UniFlow.ActionDispatcher for non-visual elements that process actions emitted by visual\n elements. Action dispatchers usually placed at the application level. Each action dispatcher\n element gets a chance to process the action in the order the elements are present in the\n DOM tree. It is important that action dispatcher elements get two-way data binding to\n application state as follows:\n\n \n\n Action dispatcher elements can include nested action dispatchers, so you can have a\n hierarchical organization of action dispatchers.\n\n ### Example:\n\n #### HTML:\n\n \n \n \n\n #### JavaScript:\n class ParentDispatcher extends UniFlow.ActionDispatcher(Polymer.Element) {\n static get is() { return 'parent-dispatcher'; }\n\n MY_ACTION(detail) {\n // do MY_ACTION processing here\n // return false if you want to prevent other action dispatchers from\n // further processing of this action\n };\n }\n\n customElements.define(ParentDispatcher.is, ParentDispatcher);\n\n ", "summary": "", "path": "action-dispatcher.html", "properties": [ { "name": "state", "type": "Object", "description": "Application state.", "privacy": "public", "sourceRange": { "file": "state-mutator.html", "start": { "line": 41, "column": 10 }, "end": { "line": 44, "column": 11 } }, "metadata": { "polymer": { "notify": true } }, "inheritedFrom": "UniFlow.StateMutator" }, { "name": "statePath", "type": "string", "description": "Path to element state in the application state tree.", "privacy": "public", "sourceRange": { "file": "state-aware.html", "start": { "line": 81, "column": 10 }, "end": { "line": 83, "column": 11 } }, "metadata": { "polymer": {} }, "inheritedFrom": "UniFlow.StateAware" }, { "name": "stateAware", "type": "boolean", "description": "", "privacy": "public", "sourceRange": { "file": "state-aware.html", "start": { "line": 85, "column": 10 }, "end": { "line": 89, "column": 11 } }, "metadata": { "polymer": {} }, "defaultValue": "true", "inheritedFrom": "UniFlow.StateAware" }, { "name": "application", "type": "Object", "description": "Application-level object that allows all state-aware objects access\nto application element. This property is shared among all state-aware\nelements and has element field initialized with reference to application\nelement. Any state-aware element can access application element using\n`getApplication()` method. Also, all state-aware elements\nadd themselves to `application.stateAwareElements` array on attach (and\nremove on detach); this list is used to send notification about\nelement state changes.", "privacy": "public", "sourceRange": { "file": "state-aware.html", "start": { "line": 101, "column": 10 }, "end": { "line": 107, "column": 11 } }, "metadata": { "polymer": {} }, "inheritedFrom": "UniFlow.StateAware" }, { "name": "actionDispatcher", "type": "boolean", "description": "", "privacy": "public", "sourceRange": { "start": { "line": 68, "column": 12 }, "end": { "line": 72, "column": 13 } }, "metadata": { "polymer": {} }, "defaultValue": "true" } ], "methods": [ { "name": "connectedCallback", "description": "Adds this element to the list of state-aware elements in the application.\nSets the value of state property to the state of the application element.", "privacy": "public", "sourceRange": { "file": "state-aware.html", "start": { "line": 116, "column": 6 }, "end": { "line": 132, "column": 7 } }, "metadata": {}, "params": [], "inheritedFrom": "UniFlow.StateAware" }, { "name": "disconnectedCallback", "description": "Removes this element from the list of state-aware elements in the\napplication.", "privacy": "public", "sourceRange": { "file": "state-aware.html", "start": { "line": 138, "column": 6 }, "end": { "line": 145, "column": 7 } }, "metadata": {}, "params": [], "inheritedFrom": "UniFlow.StateAware" }, { "name": "getApplication", "description": "Returns application element.", "privacy": "public", "sourceRange": { "file": "state-aware.html", "start": { "line": 151, "column": 6 }, "end": { "line": 153, "column": 7 } }, "metadata": {}, "params": [], "return": { "type": "Element" }, "inheritedFrom": "UniFlow.StateAware" }, { "name": "dispatchAction", "description": "Dispatches action by invoking the method with the name that matches\naction type (`detail.type`) passing detail object as a parameter;\nalso selects all children action dispatchers in the element's DOM tree and\ninvokes dispatchAction method on them. False returned by an action dispatcher method\nresults in dispatchAction method returning false (which in turn stops further processing\nof the action by other action dispatchers).", "privacy": "public", "sourceRange": { "start": { "line": 87, "column": 8 }, "end": { "line": 97, "column": 9 } }, "metadata": {}, "params": [ { "name": "detail", "type": "{type: string}" } ], "return": { "type": "boolean" } } ], "staticMethods": [], "demos": [], "metadata": {}, "sourceRange": { "start": { "line": 64, "column": 2 }, "end": { "line": 99, "column": 8 } }, "privacy": "public", "name": "UniFlow.ActionDispatcher", "attributes": [ { "name": "state", "description": "Application state.", "sourceRange": { "file": "state-mutator.html", "start": { "line": 41, "column": 10 }, "end": { "line": 44, "column": 11 } }, "metadata": {}, "type": "Object", "inheritedFrom": "UniFlow.StateMutator" }, { "name": "state-path", "description": "Path to element state in the application state tree.", "sourceRange": { "file": "state-aware.html", "start": { "line": 81, "column": 10 }, "end": { "line": 83, "column": 11 } }, "metadata": {}, "type": "string", "inheritedFrom": "UniFlow.StateAware" }, { "name": "state-aware", "description": "", "sourceRange": { "file": "state-aware.html", "start": { "line": 85, "column": 10 }, "end": { "line": 89, "column": 11 } }, "metadata": {}, "type": "boolean", "inheritedFrom": "UniFlow.StateAware" }, { "name": "application", "description": "Application-level object that allows all state-aware objects access\nto application element. This property is shared among all state-aware\nelements and has element field initialized with reference to application\nelement. Any state-aware element can access application element using\n`getApplication()` method. Also, all state-aware elements\nadd themselves to `application.stateAwareElements` array on attach (and\nremove on detach); this list is used to send notification about\nelement state changes.", "sourceRange": { "file": "state-aware.html", "start": { "line": 101, "column": 10 }, "end": { "line": 107, "column": 11 } }, "metadata": {}, "type": "Object", "inheritedFrom": "UniFlow.StateAware" }, { "name": "action-dispatcher", "description": "", "sourceRange": { "start": { "line": 68, "column": 12 }, "end": { "line": 72, "column": 13 } }, "metadata": {}, "type": "boolean" } ], "events": [], "styling": { "cssVariables": [], "selectors": [] }, "slots": [], "mixins": [ "UniFlow.StateMutator" ] }, { "description": " Whenever element needs to emit an action, this mixin should be applied.\n Action object must always include type property.\n\n ", "summary": "", "path": "action-emitter.html", "properties": [], "methods": [ { "name": "emitAction", "description": "Emits the action described by detail parameter. Detail object must always\ninclude type property. To emit the action we use custom event\nmechanism. Application element listens to the `dispatch-action` event and\ninvokes `dispatchAction` methods for all action dispatchers associated with\nthe application. Make sure your element is attached to DOM tree, otherwise\nevent will never reach your application element. It is a good practice to\nensure that `state` property is initialized (for state-aware elements) before\nemitting any actions (as `state` property is initialized on attach).", "privacy": "public", "sourceRange": { "start": { "line": 50, "column": 6 }, "end": { "line": 62, "column": 7 } }, "metadata": {}, "params": [ { "name": "detail", "type": "*" } ] } ], "staticMethods": [], "demos": [], "metadata": {}, "sourceRange": { "start": { "line": 29, "column": 2 }, "end": { "line": 64, "column": 6 } }, "privacy": "public", "name": "UniFlow.ActionEmitter", "attributes": [], "events": [ { "type": "CustomEvent", "name": "dispatch-action", "description": "dispatch-action", "metadata": {} } ], "styling": { "cssVariables": [], "selectors": [] }, "slots": [] }, { "description": " Apply this mixin to your main application element. It provides global\n state and functionality to maintain individual elements states. This mixin\n is responsible for notifying all state-aware elements about their state\n changes (provided those elements have `statePath` property defined).\n Only one element in the application is supposed to have this mixin.\n\n ### Example:\n\n #### HTML:\n\n \n\n #### JavaScript:\n class MyApp extends UniFlow.ApplicationState(Polymer.Element) {\n static get is() { return 'my-app'; }\n\n connectedCallback() {\n super.ConnectedCallback();\n\n this.state = {\n someElement: {}\n }\n }\n }\n\n customElements.define(MyApp.is,MyApp);\n\n In the example above, `` will receive notification of any changes to the state,\n as if it was declared as follows:\n\n \n\n Also, if `` has `propertyA`, on element attach this property will be assigned\n the value of `state.someElement.propertyA`, and receive all notification of the property change\n whenever the corresponding data in state tree changes. This essentially translates to following\n declaration:\n\n \n \n\n Note that data binding is one-way in both cases. Although state-aware elements can modify their\n own state, it is considered their private state and no other elements will be notified of those\n changes.\n\n ", "summary": "", "path": "application-state.html", "properties": [ { "name": "state", "type": "Object", "description": "Application state.", "privacy": "public", "sourceRange": { "file": "state-mutator.html", "start": { "line": 41, "column": 10 }, "end": { "line": 44, "column": 11 } }, "metadata": { "polymer": { "notify": true } }, "inheritedFrom": "UniFlow.StateMutator" }, { "name": "statePath", "type": "string", "description": "Path to element state in the application state tree.", "privacy": "public", "sourceRange": { "file": "state-aware.html", "start": { "line": 81, "column": 10 }, "end": { "line": 83, "column": 11 } }, "metadata": { "polymer": {} }, "inheritedFrom": "UniFlow.StateAware" }, { "name": "stateAware", "type": "boolean", "description": "", "privacy": "public", "sourceRange": { "file": "state-aware.html", "start": { "line": 85, "column": 10 }, "end": { "line": 89, "column": 11 } }, "metadata": { "polymer": {} }, "defaultValue": "true", "inheritedFrom": "UniFlow.StateAware" }, { "name": "application", "type": "Object", "description": "Application-level object that allows all state-aware objects access\nto application element. This property is shared among all state-aware\nelements and has element field initialized with reference to application\nelement. Any state-aware element can access application element using\n`getApplication()` method. Also, all state-aware elements\nadd themselves to `application.stateAwareElements` array on attach (and\nremove on detach); this list is used to send notification about\nelement state changes.", "privacy": "public", "sourceRange": { "file": "state-aware.html", "start": { "line": 101, "column": 10 }, "end": { "line": 107, "column": 11 } }, "metadata": { "polymer": {} }, "inheritedFrom": "UniFlow.StateAware" }, { "name": "actionDispatcher", "type": "boolean", "description": "", "privacy": "public", "sourceRange": { "file": "action-dispatcher.html", "start": { "line": 68, "column": 12 }, "end": { "line": 72, "column": 13 } }, "metadata": { "polymer": {} }, "defaultValue": "true", "inheritedFrom": "UniFlow.ActionDispatcher" } ], "methods": [ { "name": "connectedCallback", "description": "Adds this element to the list of state-aware elements in the application.\nSets the value of state property to the state of the application element.", "privacy": "public", "sourceRange": { "file": "state-aware.html", "start": { "line": 116, "column": 6 }, "end": { "line": 132, "column": 7 } }, "metadata": {}, "params": [], "inheritedFrom": "UniFlow.StateAware" }, { "name": "disconnectedCallback", "description": "Removes this element from the list of state-aware elements in the\napplication.", "privacy": "public", "sourceRange": { "file": "state-aware.html", "start": { "line": 138, "column": 6 }, "end": { "line": 145, "column": 7 } }, "metadata": {}, "params": [], "inheritedFrom": "UniFlow.StateAware" }, { "name": "getApplication", "description": "Returns application element.", "privacy": "public", "sourceRange": { "file": "state-aware.html", "start": { "line": 151, "column": 6 }, "end": { "line": 153, "column": 7 } }, "metadata": {}, "params": [], "return": { "type": "Element" }, "inheritedFrom": "UniFlow.StateAware" }, { "name": "dispatchAction", "description": "Dispatches action by invoking the method with the name that matches\naction type (`detail.type`) passing detail object as a parameter;\nalso selects all children action dispatchers in the element's DOM tree and\ninvokes dispatchAction method on them. False returned by an action dispatcher method\nresults in dispatchAction method returning false (which in turn stops further processing\nof the action by other action dispatchers).", "privacy": "public", "sourceRange": { "file": "action-dispatcher.html", "start": { "line": 87, "column": 8 }, "end": { "line": 97, "column": 9 } }, "metadata": {}, "params": [ { "name": "detail", "type": "{type: string}" } ], "return": { "type": "boolean" }, "inheritedFrom": "UniFlow.ActionDispatcher" }, { "name": "onDispatchAction_", "description": "Application state listens to dispatch-action method and invokes\ndispatchAction method on itself (which in turn invokes dispatchAction\non all action dispatchers declared within application element).", "privacy": "private", "sourceRange": { "start": { "line": 102, "column": 6 }, "end": { "line": 104, "column": 7 } }, "metadata": {}, "params": [ { "name": "event", "type": "!Event" } ] }, { "name": "stateChanged_", "description": "Called when state.* changes. Notifies state-aware elements of their\nstate changes, if applicable.", "privacy": "private", "sourceRange": { "start": { "line": 113, "column": 6 }, "end": { "line": 115, "column": 7 } }, "metadata": {}, "params": [ { "name": "change", "type": "!Object", "description": "the Polymer change event for the path" } ] }, { "name": "notifyStateAwareElements_", "description": "Iterates through the array of state-aware elements in the application\nand notifies them about their state change, if applicable. Note that\nstate-aware elements must be attached to DOM tree in order to receive\nnotifications.", "privacy": "private", "sourceRange": { "start": { "line": 126, "column": 6 }, "end": { "line": 149, "column": 7 } }, "metadata": {}, "params": [ { "name": "change" } ] }, { "name": "ready", "description": "Sets application.element value to this element (so all state-aware elements\nhave access to application element). Registers event listener to dispatch-action event.", "privacy": "protected", "sourceRange": { "start": { "line": 155, "column": 6 }, "end": { "line": 159, "column": 7 } }, "metadata": {}, "params": [] } ], "staticMethods": [], "demos": [], "metadata": {}, "sourceRange": { "start": { "line": 85, "column": 2 }, "end": { "line": 161, "column": 6 } }, "privacy": "public", "name": "UniFlow.ApplicationState", "attributes": [ { "name": "state", "description": "Application state.", "sourceRange": { "file": "state-mutator.html", "start": { "line": 41, "column": 10 }, "end": { "line": 44, "column": 11 } }, "metadata": {}, "type": "Object", "inheritedFrom": "UniFlow.StateMutator" }, { "name": "state-path", "description": "Path to element state in the application state tree.", "sourceRange": { "file": "state-aware.html", "start": { "line": 81, "column": 10 }, "end": { "line": 83, "column": 11 } }, "metadata": {}, "type": "string", "inheritedFrom": "UniFlow.StateAware" }, { "name": "state-aware", "description": "", "sourceRange": { "file": "state-aware.html", "start": { "line": 85, "column": 10 }, "end": { "line": 89, "column": 11 } }, "metadata": {}, "type": "boolean", "inheritedFrom": "UniFlow.StateAware" }, { "name": "application", "description": "Application-level object that allows all state-aware objects access\nto application element. This property is shared among all state-aware\nelements and has element field initialized with reference to application\nelement. Any state-aware element can access application element using\n`getApplication()` method. Also, all state-aware elements\nadd themselves to `application.stateAwareElements` array on attach (and\nremove on detach); this list is used to send notification about\nelement state changes.", "sourceRange": { "file": "state-aware.html", "start": { "line": 101, "column": 10 }, "end": { "line": 107, "column": 11 } }, "metadata": {}, "type": "Object", "inheritedFrom": "UniFlow.StateAware" }, { "name": "action-dispatcher", "description": "", "sourceRange": { "file": "action-dispatcher.html", "start": { "line": 68, "column": 12 }, "end": { "line": 72, "column": 13 } }, "metadata": {}, "type": "boolean", "inheritedFrom": "UniFlow.ActionDispatcher" } ], "events": [], "styling": { "cssVariables": [], "selectors": [] }, "slots": [], "mixins": [ "UniFlow.ActionDispatcher" ] }, { "description": " This mixin used by elements that need to render multiple models backed\n by 'list' array. You may want to use ModelView to render individual\n models in the list. The mixin supports element selection by setting predefined\n $selected property on list elements.\n\n ### Example:\n\n #### HTML:\n\n
    \n \n
\n Selected: [[selectedCount]] items\n Delete\n\n #### JavaScript:\n class ListElement extends UniFlow.StateAware(UniFlow.ListView(Polymer.Element)) {\n static get is() { return \"list-element\"; }\n\n onDeleteTap() {\n this.deleteSelected();\n }\n }\n\n customElements.define(ListElement.is, ListElement);\n\n In the example above list view element is also state-aware, meaning it has its own place\n in the application state tree. Assuming it has been declared as follows:\n\n \n\n it will be rendering `state.listElement.list` and observing changes to it. Each `model-view`\n within dom-repeat template will have `state-path` property set to\n `state.listElement.list.#` where `index` is the element's index in the array.\n\n\n ", "summary": "", "path": "list-view.html", "properties": [ { "name": "list", "type": "Array", "description": "Array which data is to be rendered by the element.", "privacy": "public", "sourceRange": { "start": { "line": 78, "column": 10 }, "end": { "line": 81, "column": 11 } }, "metadata": { "polymer": {} }, "defaultValue": "[]" }, { "name": "selectedCount", "type": "number", "description": "If element supports item selection (using meta-property $selected) then\nselectedCount property will keep track of number of selected items.", "privacy": "public", "sourceRange": { "start": { "line": 87, "column": 10 }, "end": { "line": 91, "column": 11 } }, "metadata": { "polymer": { "notify": true } }, "defaultValue": "0" }, { "name": "deleteAction", "type": "string", "description": "Action name that will be emitted when deleteSelected method is called\nwithout parameter.", "privacy": "public", "sourceRange": { "start": { "line": 97, "column": 10 }, "end": { "line": 97, "column": 30 } }, "metadata": { "polymer": {} } } ], "methods": [ { "name": "emitAction", "description": "Emits the action described by detail parameter. Detail object must always\ninclude type property. To emit the action we use custom event\nmechanism. Application element listens to the `dispatch-action` event and\ninvokes `dispatchAction` methods for all action dispatchers associated with\nthe application. Make sure your element is attached to DOM tree, otherwise\nevent will never reach your application element. It is a good practice to\nensure that `state` property is initialized (for state-aware elements) before\nemitting any actions (as `state` property is initialized on attach).", "privacy": "public", "sourceRange": { "file": "action-emitter.html", "start": { "line": 50, "column": 6 }, "end": { "line": 62, "column": 7 } }, "metadata": {}, "params": [ { "name": "detail", "type": "*" } ], "inheritedFrom": "UniFlow.ActionEmitter" }, { "name": "itemChanged_", "description": "Whenever list is set or mutated (elements added/removed), as well as\nmeta-property $selected is modified, updates selectedCount.", "privacy": "private", "sourceRange": { "start": { "line": 114, "column": 6 }, "end": { "line": 121, "column": 7 } }, "metadata": {}, "params": [ { "name": "change", "type": "!Object" } ] }, { "name": "updateSelectedCount_", "description": "Updates selectedCount property of the element by iterating the list and\ncounting each item that has meta-property $selected set.", "privacy": "private", "sourceRange": { "start": { "line": 128, "column": 6 }, "end": { "line": 134, "column": 7 } }, "metadata": {}, "params": [] }, { "name": "deleteSelected", "description": "Emits deleteAction for each selected element in the list (for which\nmeta-property $selected is set).", "privacy": "public", "sourceRange": { "start": { "line": 143, "column": 6 }, "end": { "line": 157, "column": 7 } }, "metadata": {}, "params": [ { "name": "deleteAction", "type": "string=", "description": "Action type for the action that will be emitted\n for each selected element. If not specified, `deleteAction` property of the element\n will be used." } ] } ], "staticMethods": [], "demos": [], "metadata": {}, "sourceRange": { "start": { "line": 70, "column": 2 }, "end": { "line": 159, "column": 6 } }, "privacy": "public", "name": "UniFlow.ListView", "attributes": [ { "name": "list", "description": "Array which data is to be rendered by the element.", "sourceRange": { "start": { "line": 78, "column": 10 }, "end": { "line": 81, "column": 11 } }, "metadata": {}, "type": "Array" }, { "name": "selected-count", "description": "If element supports item selection (using meta-property $selected) then\nselectedCount property will keep track of number of selected items.", "sourceRange": { "start": { "line": 87, "column": 10 }, "end": { "line": 91, "column": 11 } }, "metadata": {}, "type": "number" }, { "name": "delete-action", "description": "Action name that will be emitted when deleteSelected method is called\nwithout parameter.", "sourceRange": { "start": { "line": 97, "column": 10 }, "end": { "line": 97, "column": 30 } }, "metadata": {}, "type": "string" } ], "events": [ { "type": "CustomEvent", "name": "dispatch-action", "description": "dispatch-action", "metadata": {}, "inheritedFrom": "UniFlow.ActionEmitter" } ], "styling": { "cssVariables": [], "selectors": [] }, "slots": [], "mixins": [ "UniFlow.ActionEmitter" ] }, { "description": " Element rendering data represented by a single object (model) in the\n application state should use ModelView mixin. Model View is a powerful\n concept that encapsulates model data (likely the data received from the\n server and to be persisted to the server if modified as a result of user\n actions), status (validity of the data, flag that data was modified,\n notifications for the user, etc.). Auxiliary data supplied by action\n dispatchers and needed for display purposes or element's logic\n should be defined as element’s properties. Same applies to data\n created/modified by the element but not intended to be persisted.\n If `StateAware` mixin is used along with `ModelView`, you can take advantage\n of statePath property that indicates path to the element's state in the\n application state tree. Whenever any data is mutated by action dispatchers\n at statePath or below, the element will receive notification of its\n properties' change (even if there is no explicit binding for those\n properties). See `UniFlow.StateAware` for more details and example.\n ModelView mixin defines some properties that are intended to be overridden\n in the elements:\n\n + `validation` property allows to specify validation rules\n that will be applied when validateModel() method is called. As a result of\n this method validation status will be updated to indicate result for each\n model field that has validation rule associated with it.\n + `saveAction` property indicates which action should be emitted when\n saveModel method is called to perform save of the model.\n + `getMessage` should be overridden with the function returning message\n string for given error code (to translate validation error code to message)\n\n\n ### Example:\n\n #### HTML:\n\n \n\n #### JavaScript:\n class MyModel extends UniFlow.ModelView(Polymer.Element) {\n static get is() { return \"my-model\"; }\n \n get saveAction() { return 'MY_SAVE' }\n\n get validation() { return {\n name: (value) => {\n if (!value || !value.trim()) {\n return 'Name is not specified';\n }\n }\n }}\n\n connectedCallback() {\n this.super();\n this.fetchData();\n },\n\n fetchData() {\n this.emitAction({\n type: 'MY_FETCH',\n path: 'model'\n });\n },\n\n onSaveTap() {\n this.validateAndSave();\n }\n }\n\n customElements.define(MyModel.is, MyModel);\n\n In the example above model view has input field for `name` property and Save button. On\n element attach the action is emitted to fetch the model's data. Note that in `emitAction()` method\n the path is specified as `'model'`. ActionEmitter mixin is responsible of expanding the path\n with element's state path, ensuring that when action dispatcher gets to process the action, the\n path contains full path in the state tree. So assuming that `my-model` is declared as follows:\n\n \n\n the path in `MY_FETCH` action gets expanded to `state.myModel.model`.\n\n `validation` property is an object that contains methods for fields validation. The keys in\n this object should match model field names, the values are validation methods. Method receives\n current value of the field and should return non-falsy value (string or error code) if the value\n of the field didn't pass validation. `status.validation` object will be populated with the results\n of validation with the keys matching field names and values being objects containing two fields:\n - `invalid`: true when the value is not valid\n - `errorMessage`: the message to show to user\n\n\n So in the example above if user clicks on Save button with name not entered, they will get\n 'Name is not specified' error message on the input element. When the name is non-empty, validation\n will pass and `MY_SAVE` action will be emitted with model passed as a parameter and `'model'` as\n path.\n\n\n ", "summary": "", "path": "model-view.html", "properties": [ { "name": "model", "type": "Object", "description": "Object containing model data, usually mirroring server-side object.", "privacy": "public", "sourceRange": { "start": { "line": 138, "column": 10 }, "end": { "line": 140, "column": 11 } }, "metadata": { "polymer": {} } }, { "name": "status", "type": "Object", "description": "Object to contain model status, including validity of the data,\nflag that data was modified, notifications for the user, etc.", "privacy": "public", "sourceRange": { "start": { "line": 146, "column": 10 }, "end": { "line": 148, "column": 11 } }, "metadata": { "polymer": {} } } ], "methods": [ { "name": "emitAction", "description": "Emits the action described by detail parameter. Detail object must always\ninclude type property. To emit the action we use custom event\nmechanism. Application element listens to the `dispatch-action` event and\ninvokes `dispatchAction` methods for all action dispatchers associated with\nthe application. Make sure your element is attached to DOM tree, otherwise\nevent will never reach your application element. It is a good practice to\nensure that `state` property is initialized (for state-aware elements) before\nemitting any actions (as `state` property is initialized on attach).", "privacy": "public", "sourceRange": { "file": "action-emitter.html", "start": { "line": 50, "column": 6 }, "end": { "line": 62, "column": 7 } }, "metadata": {}, "params": [ { "name": "detail", "type": "*" } ], "inheritedFrom": "UniFlow.ActionEmitter" }, { "name": "getMessage", "description": "Function that translates error code (numeric or text) into human readable\nerror message (used to translate validation error code into error text).", "privacy": "public", "sourceRange": { "start": { "line": 176, "column": 6 }, "end": { "line": 178, "column": 7 } }, "metadata": {}, "params": [] }, { "name": "saveModel", "description": "Method emitting passed action or this.saveAction, sending model with\nthe action options.", "privacy": "public", "sourceRange": { "start": { "line": 191, "column": 6 }, "end": { "line": 207, "column": 7 } }, "metadata": {}, "params": [ { "name": "action", "type": "(Object|string)=" } ] }, { "name": "initValidationStatus_", "description": "Method initializes status.validation object with invalid = false for all\nkeys defined in this.validation object. This is needed for proper UI\nbinding (if the value of invalid attribute is undefined, paper-input is\nmisbehaving).", "privacy": "private", "sourceRange": { "start": { "line": 216, "column": 6 }, "end": { "line": 226, "column": 7 } }, "metadata": {}, "params": [] }, { "name": "validateModel", "description": "Performs validation of model object according to rules defined in\nthis.validation object. Sets status.validation. fields with\ntwo properties: invalid and errorMessage.", "privacy": "public", "sourceRange": { "start": { "line": 236, "column": 6 }, "end": { "line": 256, "column": 7 } }, "metadata": {}, "params": [], "return": { "type": "boolean", "desc": "True if all fields validated successfully (or\n this.validation is not defined in the element)." } }, { "name": "validateAndSave", "description": "Validates and saves model if there were no validation errors.", "privacy": "public", "sourceRange": { "start": { "line": 262, "column": 6 }, "end": { "line": 266, "column": 7 } }, "metadata": {}, "params": [ { "name": "action", "type": "string=", "description": "Optional action type to emit for save action." } ] }, { "name": "modelViewModelChanged_", "description": "Observer of any changes to the model. Resets status object and initializes\nvalidation status.", "privacy": "private", "sourceRange": { "start": { "line": 274, "column": 6 }, "end": { "line": 288, "column": 7 } }, "metadata": {}, "params": [ { "name": "change", "type": "!Object" } ] } ], "staticMethods": [], "demos": [], "metadata": {}, "sourceRange": { "start": { "line": 129, "column": 2 }, "end": { "line": 290, "column": 6 } }, "privacy": "public", "name": "UniFlow.ModelView", "attributes": [ { "name": "model", "description": "Object containing model data, usually mirroring server-side object.", "sourceRange": { "start": { "line": 138, "column": 10 }, "end": { "line": 140, "column": 11 } }, "metadata": {}, "type": "Object" }, { "name": "status", "description": "Object to contain model status, including validity of the data,\nflag that data was modified, notifications for the user, etc.", "sourceRange": { "start": { "line": 146, "column": 10 }, "end": { "line": 148, "column": 11 } }, "metadata": {}, "type": "Object" } ], "events": [ { "type": "CustomEvent", "name": "dispatch-action", "description": "dispatch-action", "metadata": {}, "inheritedFrom": "UniFlow.ActionEmitter" } ], "styling": { "cssVariables": [], "selectors": [] }, "slots": [], "mixins": [ "UniFlow.ActionEmitter" ] } ] } ================================================ FILE: application-state.html ================================================ ================================================ FILE: bower.json ================================================ { "name": "uniflow-polymer", "version": "0.6.0", "authors": [ "Andrei Militeev " ], "description": "A straightforward way to architect Polymer application using unidirectional data flow.", "keywords": [ "web-component", "polymer", "uniflow", "unidirectional", "flow" ], "license": "https://raw.githubusercontent.com/google/uniflow-polymer/master/LICENSE", "homepage": "https://github.com/google/uniflow-polymer/", "ignore": [ "/.*", "/test/" ], "dependencies": { "polymer": "Polymer/polymer#^2.0.0" }, "devDependencies": { "app-route": "PolymerElements/app-route#^2.0.2", "iron-component-page": "PolymerElements/iron-component-page#^3.0.0", "iron-demo-helpers": "PolymerElements/iron-demo-helpers#^2.0.0", "iron-icon": "PolymerElements/iron-icon#^2.0.0", "iron-icons": "PolymerElements/iron-icons#^2.0.0", "iron-test-helpers": "PolymerElements/iron-test-helpers#^2.0.0", "paper-styles": "PolymerElements/paper-styles#^2.0.0", "test-fixture": "PolymerElements/test-fixture#3.0.0-rc.1", "web-component-tester": "^v6.0.0", "todomvc-app-css": "^2.1.0", "iron-localstorage": "PolymerElements/iron-localstorage#^2.0.0" } } ================================================ FILE: index.html ================================================ ================================================ FILE: list-view.html ================================================ ================================================ FILE: model-view.html ================================================ ================================================ FILE: state-aware.html ================================================ ================================================ FILE: state-mutator.html ================================================ ================================================ FILE: test/action-dispatcher_test.html ================================================ UniFlow.ActionDispatcher tests ================================================ FILE: test/action-emitter_test.html ================================================ UniFlow.ActionEmitter tests ================================================ FILE: test/application-state_test.html ================================================ UniFlow.ApplicationState tests ================================================ FILE: test/list-view_test.html ================================================ UniFlow.ListView tests ================================================ FILE: test/model-view_test.html ================================================ UniFlow.ModelView tests ================================================ FILE: test/state-aware_test.html ================================================ UniFlow.StateAware tests ================================================ FILE: todomvc/README.md ================================================ # \ ToDo MVC application implemented with UniFlow for Polymer 2.x ## Install Bower Dependencies Run `bower install` ## Install the Polymer-CLI Make sure you have the [Polymer CLI](https://www.npmjs.com/package/polymer-cli) installed. ## Run the Application Run `polymer serve` to serve your application locally. Open the by adding todomvc to the url, for example: http://127.0.0.1:8081/components/uniflow-polymer/todomvc ================================================ FILE: todomvc/elements/todo-action-dispatcher.html ================================================ ================================================ FILE: todomvc/elements/todo-app.html ================================================ ================================================ FILE: todomvc/elements/todo-footer.html ================================================ ================================================ FILE: todomvc/elements/todo-header.html ================================================ ================================================ FILE: todomvc/elements/todo-item.html ================================================ ================================================ FILE: todomvc/elements/todo-items.html ================================================ ================================================ FILE: todomvc/elements/todo-styles.html ================================================ ================================================ FILE: todomvc/index.html ================================================ TodoMVC with UniFlow ================================================ FILE: todomvc/manifest.json ================================================ { "name": "todo", "short_name": "todo", "description": "ToDo MVC application implemented with UniFlow for Polymer", "start_url": "/", "display": "standalone" } ================================================ FILE: todomvc/scripts/actions.js ================================================ window.todo = window.todo || {}; todo.actions = { INIT_APPLICATION: "INIT_APPLICATION", ADD_TODO: "ADD_TODO", REMOVE_TODO: "REMOVE_TODO", UPDATE_TODO: "UPDATE_TODO", SELECTION_CHANGED: "SELECTION_CHANGED", CLEAR_COMPLETED: "CLEAR_COMPLETED" }