I have a page where I want to include three separate views (one showing all the data and ones with different summaries) on the same set of data.
I'm looking for a way to represent each view as a Polymer element and have each one update whenever the data changes. These changes will be to the values of properties of objects which are stored in an array. It is the array that is shared between the components.
I've found an approach that works by firing an event when there is a change to the data, listening for it outside the components, and then calling notifyPath
— but it is somewhat unwieldy and likely to be more so as I grow my code its current state (a simple demo with two Polymer elements, one of which is readonly) to the end goal (three elements, all of which can read and write to the data).
Is there a simpler way to share changes between components than this?
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>polymer-test</title>
<script>
(function() {
var data = [{
name: "Alice",
amount: 100
}, {
name: "Bob",
amount: 200
}];
document.addEventListener('WebComponentsReady', function() {
document.querySelector('example-one').data = data;
document.querySelector('example-two').data = data;
document.querySelector('example-two').addEventListener('there-is-a-change', function(e) {
document.querySelector('example-one').notifyPath(e.detail.path);
})
});
})();
</script>
<script src="/bower_components/webcomponentsjs/webcomponents-loader.js"></script>
<link rel="import" href="/src/polymer-test-app/example-one.html">
<link rel="import" href="/src/polymer-test-app/example-two.html">
</head>
<body>
<h1>One</h1>
<example-one></example-one>
<h1>Two</h1>
<example-two></example-two>
</body>
</html>
example-one.html
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/polymer/lib/elements/dom-repeat.html">
<dom-module id="example-one">
<template>
<style>
:host {
display: block;
}
</style>
<table>
<tbody>
<template is="dom-repeat" items="{{data}}">
<tr>
<td>{{item.name}}</td>
<td>{{item.amount}}</td>
</tr>
</template>
</tbody>
</table>
</template>
<script>
class ExampleOne extends Polymer.Element {
static get is() {
return 'example-one';
}
static get properties() {
return {
data: {
type: Array,
notify: true,
value() {
return [];
}
}
};
}
}
window.customElements.define(ExampleOne.is, ExampleOne);
</script>
</dom-module>
example-two.html
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/polymer/lib/elements/dom-repeat.html">
<dom-module id="example-two">
<template>
<style>
:host {
display: block;
}
</style>
<table>
<tbody>
<template is="dom-repeat" items="{{data}}">
<tr>
<td>{{item.name}}</td>
<td><input value="{{item.amount::input}}"></td>
</tr>
</template>
</tbody>
</table>
</template>
<script>
class ExampleTwo extends Polymer.Element {
static get is() {
return 'example-two';
}
static get properties() {
return {
data: {
type: Array,
notify: true,
value() {
return [];
}
}
};
}
static get observers() {
return [
'arrayChanged(data.*)'
]
}
arrayChanged(data) {
console.log("Changed!");
this.dispatchEvent(new CustomEvent("there-is-a-change", {
detail: {
path: data.path
}
}));
}
}
window.customElements.define(ExampleTwo.is, ExampleTwo);
</script>
</dom-module>
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…