diff --git a/src/platform/web/ui/general/BaseUpdateView.js b/src/platform/web/ui/general/BaseUpdateView.js new file mode 100644 index 00000000..4f346499 --- /dev/null +++ b/src/platform/web/ui/general/BaseUpdateView.js @@ -0,0 +1,58 @@ +/* +Copyright 2021 The Matrix.org Foundation C.I.C. + +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. +*/ + +export class BaseUpdateView { + constructor(value) { + this._value = value; + // TODO: can avoid this if we adopt the handleEvent pattern in our EventListener + this._boundUpdateFromValue = null; + } + + mount(options) { + const parentProvidesUpdates = options && options.parentProvidesUpdates; + if (!parentProvidesUpdates) { + this._subscribe(); + } + } + + unmount() { + this._unsubscribe(); + } + + get value() { + return this._value; + } + + _updateFromValue(changedProps) { + this.update(this._value, changedProps); + } + + _subscribe() { + if (typeof this._value?.on === "function") { + this._boundUpdateFromValue = this._updateFromValue.bind(this); + this._value.on("change", this._boundUpdateFromValue); + } + } + + _unsubscribe() { + if (this._boundUpdateFromValue) { + if (typeof this._value.off === "function") { + this._value.off("change", this._boundUpdateFromValue); + } + this._boundUpdateFromValue = null; + } + } +} diff --git a/src/platform/web/ui/general/TemplateView.js b/src/platform/web/ui/general/TemplateView.js index 85345c53..8b0da9df 100644 --- a/src/platform/web/ui/general/TemplateView.js +++ b/src/platform/web/ui/general/TemplateView.js @@ -16,6 +16,7 @@ limitations under the License. import { setAttribute, text, isChildren, classNames, TAG_NAMES, HTML_NS } from "./html.js"; import {errorToDOM} from "./error.js"; +import {BaseUpdateView} from "./BaseUpdateView.js"; function objHasFns(obj) { for(const value of Object.values(obj)) { @@ -38,37 +39,15 @@ function objHasFns(obj) { - add subviews inside the template */ // TODO: should we rename this to BoundView or something? As opposed to StaticView ... -export class TemplateView { +export class TemplateView extends BaseUpdateView { constructor(value, render = undefined) { - this._value = value; + super(value); // TODO: can avoid this if we have a separate class for inline templates vs class template views this._render = render; this._eventListeners = null; this._bindings = null; this._subViews = null; this._root = null; - // TODO: can avoid this if we adopt the handleEvent pattern in our EventListener - this._boundUpdateFromValue = null; - } - - get value() { - return this._value; - } - - _subscribe() { - if (typeof this._value?.on === "function") { - this._boundUpdateFromValue = this._updateFromValue.bind(this); - this._value.on("change", this._boundUpdateFromValue); - } - } - - _unsubscribe() { - if (this._boundUpdateFromValue) { - if (typeof this._value.off === "function") { - this._value.off("change", this._boundUpdateFromValue); - } - this._boundUpdateFromValue = null; - } } _attach() { @@ -96,17 +75,15 @@ export class TemplateView { } else { throw new Error("no render function passed in, or overriden in subclass"); } - const parentProvidesUpdates = options && options.parentProvidesUpdates; - if (!parentProvidesUpdates) { - this._subscribe(); - } + // takes care of update being called when needed + super.mount(options); this._attach(); return this._root; } unmount() { this._detach(); - this._unsubscribe(); + super.unmount(); if (this._subViews) { for (const v of this._subViews) { v.unmount(); @@ -118,10 +95,6 @@ export class TemplateView { return this._root; } - _updateFromValue(changedProps) { - this.update(this._value, changedProps); - } - update(value) { this._value = value; if (this._bindings) {