web-dev-qa-db-ja.com

Angular:変更されたdom要素を一時的に強調表示する方法は?

自分でソリューションを実装する前に、データバインドされたプロパティ値が変更されたときに、要素のスタイルを変更する簡単な方法(短いハイライト)があるかどうかを知りたいと思います。

私のDOMには多くの要素があるため、コンポーネントに専用のプロパティを保存して維持したくありません。

強調する私の要素は、従来の入力フォームの要素です。

    <tr field label="Lieu dépôt">
        <select class="cellinput" #lieuDepotBon [(ngModel)]="rapport.LieuDepotBon" (ngModelChange)="changeRapport({LieuDepotBon:$event})">
            <option [ngValue]="null"></option>
            <option [ngValue]="i" *ngFor="let depotBonChoice of DepotBonInterventionValues; let i = index">{{DepotBonIntervention[i]}}</option>
        </select>
    </tr>
    <tr field *ngIf="rapport.LieuDepotBon==DepotBonIntervention.Autre" label="Autre lieu">
        <input class="cellinput" #autreLieuDepotBon [(ngModel)]="rapport.AutreLieuDepotBon" (ngModelChange)="changeRapport({AutreLieuDepotBon:autreLieuDepotBon.value})" />
    </tr>

Angular2がngModelディレクティブを含む要素に設定した特別なクラススタイルについて聞いたが、これは私が必要なことを実行するのに役立つかもしれないが、それについてそれ以上見つけることができなかった。

20

これが私の解決策です。

他のユーザーがリアルタイムで変更したフォームのデータを強調したかったのです。

私のHTMLフォームでは、ネイティブHTML要素をAngularコンポーネントに置き換えました。ネイティブ要素のタイプごとに、新しいAngularハイライトサポートのあるコンポーネントを作成しました。各コンポーネントControlValueAccessor Angularインターフェースを実装します。

親フォームで、ネイティブ要素を置き換えました:

<input [(ngModel)]="itinerary.DetailWeather" />

私のカスタム要素:

<reactive-input [(ngModel)]="itinerary.DetailWeather"></reactive-input>

親フォームに対してAngularがdetectChanges()を呼び出す場合、フォームのコンポーネントによって入力として使用されるすべてのデータをチェックします。

コンポーネントがControlValueAccessorで、アプリケーションモデルで変更が発生した場合、メソッドはControlValueAccessor .writeValue(value)を呼び出します。メモリ内でデータが変更されたときに呼び出されるメソッドです。一時的にスタイルを更新してハイライトを追加するためのフックとして使用します。

これがカスタム要素です。 Angularアニメーションを使用して、境界線の色を更新し、元の色にフェードバックしました。

import { Component, Input, forwardRef, ChangeDetectorRef } from '@angular/core';
import { ControlValueAccessor,  NG_VALUE_ACCESSOR  } from '@angular/forms';
import { trigger, state, style, animate, transition, keyframes } from '@angular/animations';

@Component(
{
  selector: 'reactive-input',
  template: `<input class="cellinput" [(ngModel)]="value" [@updatingTrigger]="updatingState" />`,
  styles: [`.cellinput {  padding: 4px }`],
  animations: [
    trigger( 
      'updatingTrigger', [
        transition('* => otherWriting', animate(1000, keyframes([
          style ({ 'border-color' : 'var( --change-detect-color )', offset: 0 }),
          style ({ 'border-color' : 'var( --main-color )', offset: 1 })
        ])))
    ])
  ],
  providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => ReactiveInputComponent), multi: true } ]
})
export class ReactiveInputComponent implements ControlValueAccessor {

  public updatingState : string = null;
  _value = '';

  // stores the action in the attribute (onModelChange) in the html template:
  propagateChange:any = ( change ) => {};

  constructor( private ref: ChangeDetectorRef ) { }

  // change from the model
  writeValue(value: any): void
  {
    this._value = value; 
    this.updatingState = 'otherWriting';

    window.setTimeout( () => {
      this.updatingState = null;
    }, 100 );

    // model value has change so changes must be detected (case ChangeDetectorStrategy is OnPush)
    this.ref.detectChanges();
  }

  // change from the UI
  set value(event: any)
  {
    this._value = event;
    this.propagateChange(event);
    this.updatingState = null;
  }

  get value()
  {
    return this._value;
  }

  registerOnChange(fn: any): void { this.propagateChange = fn; }
  registerOnTouched(fn: () => void): void {}
  setDisabledState?(isDisabled: boolean): void {};
}
2

私が考えることができる最も簡単でクリーンな方法は、次のように2つのcssクラスを実装することです:

.highlight{
    background-color: #FF0;
}
.kill-highlight{
    background-color: #AD310B;
    -webkit-transition: background-color 1000ms linear;
    -ms-transition: background-color 1000ms linear;
    transition: background-color 1000ms linear;
}

そして、それらの両方に連続的に要素に影響を与えます。それが役に立てば幸い

3
Taha Zgued

DOM要素を一瞬ハイライトするには、setTimeout()を使用してCSSクラスを追加または削除します

デモを確認

[〜#〜] html [〜#〜]

_<mat-form-field [ngClass]="{'changed': isChanged}">
  <mat-select [(ngModel)]="yourModel" (ngModelChange)="modelChanged($event)">
     <mat-option value="1">1</mat-option>
     <mat-option value="2">2</mat-option>
     <mat-option value="3">3</mat-option>
  </mat-select>
</mat-form-field>
_

TypeScript

_isChanged: boolean = false
modelChanged(value) {
   console.log('model changed')

   this.isChanged = true
   setTimeout(() => {
       this.isChanged = false
   }, 1000);
}
_

[〜#〜] css [〜#〜]

_.changed {
    transition: color 0.4s ease-in, text-shadow 0.4s ease-in, background-color 0.5s linear 0s;
    text-shadow: #bbb 2px 2px 2px;
    background-color: #ffffcc;
    color: #BF1722;
}
_

注:アプリケーションがミリ秒単位で変更される場合は、setTimeout()の時間をに減らす必要がありますアプリケーション要件に従って、0.5sまたは0.3s

この問題を指摘してくれたIngoBürkに感謝

0
WasiF