Angular:如何临时高亮刚刚变化的dom个元素?
Angular: How to temporarily highlight dom elements that have just changed?
在我自己实施解决方案之前,我想知道当数据绑定 属性 值刚刚发生变化时,是否有一种简单的方法来更改元素的样式(简要突出显示)。
我的 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 指令的元素上设置的特殊 class 样式可以帮助完成我需要的事情,但我找不到更多相关信息。
我能想到的最简单和简洁的方法是像这样实现 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;
}
然后依次影响到元素。
希望有帮助
这是我的解决方案。
我想突出显示其他用户实时更改的表单中的数据。
在我的 HTML 表单中,我用 Angular 组件替换了原生 html 元素。对于每种类型的原生元素,我都创建了一个新的 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 {};
}
要暂时突出显示 DOM 元素,请使用 setTimeout()
添加或删除 CSS class
check demo
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>
打字稿
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 根据您的应用要求。
感谢 Ingo Bürk 指出这个问题
在我自己实施解决方案之前,我想知道当数据绑定 属性 值刚刚发生变化时,是否有一种简单的方法来更改元素的样式(简要突出显示)。
我的 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 指令的元素上设置的特殊 class 样式可以帮助完成我需要的事情,但我找不到更多相关信息。
我能想到的最简单和简洁的方法是像这样实现 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;
}
然后依次影响到元素。 希望有帮助
这是我的解决方案。
我想突出显示其他用户实时更改的表单中的数据。
在我的 HTML 表单中,我用 Angular 组件替换了原生 html 元素。对于每种类型的原生元素,我都创建了一个新的 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 {};
}
要暂时突出显示 DOM 元素,请使用 setTimeout()
添加或删除 CSS class
check demo
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>
打字稿
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 根据您的应用要求。
感谢 Ingo Bürk 指出这个问题