Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular: How to temporarily highlight dom elements that have just changed?

Tags:

Before implementing a solution on my own I would like to know if there is a simple manner to change the style of an element (a brief highlight) when the data bound property value has just change.

There are lot of elements in my DOM so I do not not want to store and maintain a dedicated property in component.

My elements to highlight are traditional input form's elements:

    <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> 

I heard about special class styles set by Angular2 on element with ngModel directive that could help do what I need but I could not find more about it.

like image 200
Anthony Brenelière Avatar asked May 18 '17 08:05

Anthony Brenelière


2 Answers

The easiest and cleaner way I can think of is to implement 2 css classes like so:

.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; } 

and then affect both of them successively to the element. hope that helps

like image 75
Taha Zgued Avatar answered Oct 04 '22 00:10

Taha Zgued


Here is my solution.

I wanted to highlight the datas in the Form that are changed by other users in real-time.

In my HTML form, I replaced native html elements by Angular components. For each type of native element I created a new Angular Component with Highlight support. Each component implements the ControlValueAccessor Angular interface.

In the parent form I replaced the native element:

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

by my custom element:

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

When Angular calls detectChanges() for the parent form, it does check all the datas that are used as inputs by the components of the form.

If a component is a ControlValueAccessor, and a change occurred in the application model, it does call the method ControlValueAccessor.writeValue( value ). It is the method that is called when the data changed in memory. I use it as a hook to update temporarily the style to add the highlight.

Here is the custom element. I used Angular Animations for updating the border color and fade back to the original color.

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 {}; } 
like image 31
Anthony Brenelière Avatar answered Oct 03 '22 23:10

Anthony Brenelière