Обновить привязку свойства элементов - PullRequest
0 голосов
/ 15 апреля 2020

У меня есть веб-компонент на основе LitElement, который отображает mdw-диалог с пользовательским элементом внутри, который использует свойство родительского компонента. Когда пользователь нажимает кнопку, появляется диалоговое окно, отображающее пару полей ввода. Все это прекрасно работает, но я хочу, чтобы свойство сбрасывалось на пустой объект при каждом нажатии кнопки, прежде чем отобразится диалоговое окно, и, хотя я могу легко это сделать - оно, похоже, не влияет на элементы диалога.

Родительский элемент

export class PageApplications extends LitElement {

    static get properties() {
        return {
            application: { type: Object }
        }
    }

    constructor() {
        super();
        this.application = {};
    }

    onMouseOver(event) {
        this.shadowRoot.querySelector('mwc-fab').extended = ('mouseenter' === event.type);
    }

    openDialog() {
        console.log('PageApplication.openDialog:', this.application);
        this.application = {};
        let dialog = this.shadowRoot.querySelector('mwc-dialog');
        dialog.requestUpdate;
        dialog.open = true;
    }

    closedDialog(event) {
        console.log('closedDialog:', this.application)
        if ('ok' === event.detail.action) {
            // NOP
        }
    }

    render() {
        console.log('PageApplication.render', this.application);
        return html`
            <style type="text/css">
                mwc-fab {
                    position: fixed;
                    right: 1rem;
                }
                mwc-list {
                    background-color: #FFF;
                }
            </style>
            <mwc-fab showIconAtEnd icon="add_circle" label="New Application" 
                @mouseenter="${this.onMouseOver}"
                @mouseout="${this.onMouseOver}"
                @click="${this.openDialog}"
                >
            </mwc-fab>
            <mwc-dialog heading="Create Application"
                @closed="${this.closedDialog}">
                <cnvy-create-application
                    .application="${this.application}"
                ></cnvy-create-application>
                <mwc-button
                    slot="primaryAction"
                    dialogAction="ok"
                >Create</mwc-button>
                <mwc-button
                    slot="secondaryAction"
                    dialogAction="cancel"
                >Cancel</mwc-button>            
            </mwc-dialog>
            <h2>Applications</h2>

, как вы можете видеть, свойство приложения связано с элементом cnvy-create-application

export class ConvoyCreateApplication extends LitElement {

    constructor() {
        super();
    }

    static get properties() {
        return {
            application: { type: Object }
        }
    }

    render() {
        console.log('ConvoyCreateApplication.render', this.application);
        return html`
            <style>
                mwc-formfield {
                    display: block;
                }
            </style>
            <mwc-formfield>
                <mwc-textfield 
                    placeholder="Name" 
                    helper="Name of application"
                    .value="${this.application.name}"
                    @change="${e => this.application.name = e.target.value}"
                    ></mwc-textfield>
            </mwc-formfield>
            <mwc-formfield>
                <mwc-textarea 
                    rows="2" 
                    placeholder="Description" 
                    helper="Short description"
                    .value="${this.application.description}"
                    @change="${e => this.application.description = e.target.value}"
                ></mwc-textfield>
            </mwc-formfield>
        `;
    }

}
customElements.define('cnvy-create-application', ConvoyCreateApplication);

Проблема в том, что при первом нажатии кнопка, диалоговое окно отображается, как и ожидалось, и каждое текстовое поле говорит «неопределено», что, вероятно, нормально, поскольку реквизиты не определены в пустом объекте. Я ввожу значения соответственно «a» и «b» и нажимаю «ОК» в диалоговом окне, и консоль печатает

closedDialog: {name: "a", description: "b"}

, как и ожидалось. Если я затем снова нажму кнопку, свойство «application» должно быть сброшено на пустой объект, но пользовательский интерфейс отображает текстовые поля с «a» и «b», и если я изменю «b» на «d», только «d» отправляется обратно

closedDialog: {description: "d"}

означает, что объект приложения был фактически сброшен в пустое состояние, НО это не то, что показано ... итак, как мне запустить обновление? Я пробовал различные "update", "requestUpdate" .. и такие методы жизненного цикла, но безрезультатно.

1 Ответ

0 голосов
/ 16 апреля 2020

mwc-textfield внутренне использует собственный input и передает ему привязку свойства value. Это один из случаев, когда свойство обновляется из нескольких источников (из .value="${this.application.name}" и из DOM при редактировании текста). В этом сценарии lit-html может не знать, как обновить значение и может вызвать смещение между данными и тем, что на самом деле показано. Чтобы решить эту проблему, вы можете использовать директиву live : она

проверяет значение привязки по значению live DOM вместо ранее привязанного значения, при определении, обновлять ли значение.

import {live} from 'lit-html/directives/live';

// ...

render() {
  return html`
    <mwc-textfield
      .value=${live(this.application.name)}
               ^^^^
    ></mwc-textfield>
  `;
}

В openDialog() вы, вероятно, пропустили круглые скобки в dialog.requestUpdate˅;, хотя нет необходимости вызывать его: достаточно this.application = {}; для запуска обновления.

Чтобы текстовые поля не отображались undefined, вы можете либо указать запасное значение в привязке

<mwc-textfield
  .value=${live(this.application.name || '')}
></mwc-textfield>

, либо инициализировать всю структуру данных пустыми значениями:

constructor() {
  this.application = {
    a: '',
    b: '',
    // ...
  };
}
...