This repository has been archived by the owner on Sep 10, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 21
/
state-aware.html
157 lines (126 loc) · 4.74 KB
/
state-aware.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
<!--
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.
-->
<link rel="import" href="../polymer/polymer-element.html">
<script type="text/javascript">
var UniFlow = window.UniFlow || {};
/**
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:
<template>
<div>Value A: [[state.valueA]]</div>
<div>Value B: [[valueB]]</div>
</template>
#### JavaScript:
class MyElement extends UniFlow.StateAware(Polymer.Element) {
static get is() { return 'my-element'; }
static get properties() {
return {
valueB: String
}
}
}
customElement.define(MyElement.is, MyElement);
When above element is declared as follows:
<my-element state-path="state.myElement"></my-element>
it will be notified about changes (and render those) to `state.valueA` or
`state.myElement.valueB` in action dispatchers or other state mutating
elements.
@polymer
@mixinFunction
*/
UniFlow.StateAware = Polymer.dedupingMixin((base) =>
class extends base {
static get properties() {
return {
/**
* Application state, shared among application and all state-aware elements.
* This property is initialized when element is attached.
*/
state: {
type: Object
},
/**
* Path to element state in the application state tree.
*/
statePath: {
type: String
},
stateAware: {
type: Boolean,
value: true,
reflectToAttribute: true
},
/**
* Application-level object that allows all state-aware objects access
* to application element. This property is shared among all state-aware
* elements and has element field initialized with reference to application
* element. Any state-aware element can access application element using
* `getApplication()` method. Also, all state-aware elements
* add themselves to `application.stateAwareElements` array on attach (and
* remove on detach); this list is used to send notification about
* element state changes.
*/
application: {
type: Object,
value: {
element: null,
stateAwareElements: []
}
}
}
}
/**
* Adds this element to the list of state-aware elements in the application.
* Sets the value of state property to the state of the application element.
*/
connectedCallback() {
super.connectedCallback();
this.push('application.stateAwareElements', this);
// Copying application's element state to this element. ApplicationState behavior is
// responsible of notifying state aware elements about application's state changes.
if (!this.get('state') && this.get('application.element.state')) {
this.set('state', this.get('application.element.state'));
}
// If this element's state exists, the properties ot the element are
// initialized from state.
if (this.statePath && this.get(this.statePath)) {
Object.keys(this.get(this.statePath)).forEach((key) => {
this.set(key, this.get([this.statePath, key]));
});
}
}
/**
* Removes this element from the list of state-aware elements in the
* application.
*/
disconnectedCallback() {
const index = this.application.stateAwareElements.indexOf(this);
if (index !== -1) {
this.application.stateAwareElements.splice(index, 1);
}
super.disconnectedCallback();
}
/**
* Returns application element.
* @return {Element}
*/
getApplication() {
return this.get('application.element');
}
});
</script>