| // Copyright 2019 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| /** |
| * @fileoverview |
| * app-management-dom-switch is used to select one element to be displayed at a |
| * time from a group of elements. When an element is selected, it is attached |
| * to the DOM. When another element is selected, the first element is |
| * detached, meaning only one of the elements is attached at a time. |
| * |
| * The elements are selected by giving them each a route-id attribute, then |
| * setting the route property of the dom-switch equal to the route-id of the |
| * element to be shown. |
| * |
| * Data binding from the parent element of the dom-switch to its child |
| * elements works as usual. |
| * |
| * Usage: |
| * <parent-element> |
| * <app-management-dom-switch id="view-selector"> |
| * <template> |
| * <view-one route-id="view-one" title="[[parentProperty]]"></view-one> |
| * <view-two route-id="view-two"></view-two> |
| * <view-three route-id="view-three"></view-three> |
| * </template> |
| * </app-management-dom-switch> |
| * </parent-element> |
| * |
| * this.$['view-selector'].route = 'view-two'; |
| */ |
| |
| Polymer({ |
| is: 'app-management-dom-switch', |
| |
| behaviors: [Polymer.Templatizer], |
| |
| properties: { |
| /** |
| * Should contain the route-id of one of the elements within the dom-switch. |
| * @private {?string} |
| */ |
| route: { |
| type: String, |
| observer: 'onRouteChanged_', |
| }, |
| |
| /** |
| * The template instance. |
| * @private {?Element} |
| */ |
| instance_: { |
| type: Object, |
| value: null, |
| }, |
| |
| /** |
| * Maps the route-id of each element within the dom-switch to the element |
| * itself. |
| * @private {Object<string, Element>} |
| */ |
| children_: { |
| type: Object, |
| value: () => ({}), |
| }, |
| |
| /** |
| * The element whose route-id corresponds to the current route. This is the |
| * only element within the dom-switch which is attached to the DOM. |
| * @private {?Element} |
| */ |
| selectedChild_: { |
| type: Object, |
| value: null, |
| }, |
| }, |
| |
| attached: function() { |
| const template = this.getContentChildren()[0]; |
| this.templatize(template); |
| |
| // This call stamps all the child elements of the dom-switch at once |
| // (calling their created Polymer lifecycle callbacks). If optimisations |
| // are required in the future, it may be possible to only stamp children |
| // on demand as they are rendered. |
| this.instance_ = this.stamp({}); |
| |
| const children = this.instance_.root.children; |
| for (const child of children) { |
| this.children_[child.getAttribute('route-id')] = child; |
| } |
| }, |
| |
| /** |
| * @param {string} newRouteId |
| */ |
| onRouteChanged_: function(newRouteId) { |
| const newSelectedChild = this.children_[newRouteId]; |
| assert( |
| newSelectedChild, |
| 'The route must be equal to the route-id of a child element.'); |
| |
| if (this.selectedChild_) { |
| this.parentNode.replaceChild(newSelectedChild, this.selectedChild_); |
| } else { |
| this.parentNode.insertBefore(newSelectedChild, this); |
| } |
| |
| this.selectedChild_ = newSelectedChild; |
| }, |
| |
| /** |
| * TODO(dpapad): Delete this method once migration to Polymer 2 has finished. |
| * @param {string} prop |
| * @param {Object} value |
| */ |
| _forwardParentProp: function(prop, value) { |
| if (this.instance_) { |
| this.instance_[prop] = value; |
| } |
| }, |
| |
| /** |
| * TODO(dpapad): Delete this method once migration to Polymer 2 has finished. |
| * @param {string} path |
| * @param {Object} value |
| */ |
| _forwardParentPath: function(path, value) { |
| if (this.instance_) { |
| this.instance_.notifyPath(path, value, true); |
| } |
| }, |
| |
| /** |
| * @param {string} prop |
| * @param {Object} value |
| */ |
| _forwardHostPropV2: function(prop, value) { |
| if (this.instance_) { |
| this.instance_.forwardHostProp(prop, value); |
| } |
| }, |
| }); |