将模型更改注册到 MDL 输入元素

Register model changes to MDL input elements

将 MDL 与框架集成时,框架将直接设置输入值,但 MDL 库不会注意到这些更改,因为它们很可能绑定到单击和更改事件。例如,如果我有:

<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
    <input class="mdl-textfield__input" type="text" id="joke" pattern="-?[0-9]*(\.[0-9]+)?">
    <label class="mdl-textfield__label" for="joke">Joke...</label>
    <span class="mdl-textfield__error">Input is not a number!</span>
</div>

然后用一些 javascript:

更改值
document.getElementById('joke').value=text;

元素标签不动,被文字覆盖。总之,is-dirtyclass没有设置

这是一个更详细地说明问题的示例。 https://plnkr.co/6pAh7ApQT8TUUS9G9QBg

我目前正在 Angular2 中从事一个项目,但我认为总体问题与框架无关。我希望有比我的 'answer'.

更好的解决方案

更新的答案:

绑定到 class 列表,https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ngClass,可能是更好的方法:

示例:

<div class="mdl-textfield mdl-js-textfield mdl-text-field--floating-label"
    [class.is-dirty]=" val != null && val != '' ">

或者对于 mdl-tabs:

<div class="mdl-tabs__panel"
    [class.is-active]="val_is_active_tab">

或者对于 mdl-checkboxes:

<label class="mdl-radio mdl-js-radio mdl-js-ripple-effect"
      [class.is-checked]="val == 1">

原回答:

对于我的项目,我的临时解决方案是放入一些非常非 angular2 的代码:

private thingsToDirty = [];
ngAfterViewChecked() {
    for (let id of this.thingsToDirty) {
        let el: any = document.getElementById(id);
        if (el != undefined && 
        el.parentNode.className.indexOf("is-dirty") == -1) {
            el.parentNode.className += " is-dirty";
        }
    }
    this.thingsToDirty.length = 0;
}

ngOnInit() {
    this.something.getJSONfromServer().subscribe( data => {
        this.thing = data;
        this.thingsToDirty.push('thing_id');
    });
}

我找到的最佳解决方案是使用指令。您可以在元素上调用 checkDirty()。

import { Directive, AfterViewInit, ElementRef, AfterViewChecked} from '@angular/core';
declare var componentHandler: any;

@Directive({
    selector: '[mdl]'
})
export class MDL implements AfterViewInit {
    constructor(private element: ElementRef) {
    }

    ngAfterViewInit() {
        componentHandler.upgradeAllRegistered();
    }

    ngAfterViewChecked() {
        let mdlField = this.element.nativeElement.MaterialTextfield;
        if (mdlField) {
            mdlField.checkDirty();
            mdlField.checkValidity();
        }
    }
}

然后,在您的模板中,只需将此指令包含在 mdl 输入

的父级 div 中
<div mdl class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdl-cell mdl-cell--5-col mdl-cell--8-col-tablet mdl-cell--4-col-phone">
    <label class="mdl-textfield__label" for="promoCode_{{inRibbon}}">Promo code</label>
    <input class="mdl-textfield__input" type="text" id="promoCode" name="promoCode_{{inRibbon}}" [ngModelOptions]="{standalone: true}" [(ngModel)]="itemAvailabilityRequest.promoCode">
</div>