Extending native HTML inputs 

HTML

  • Form elements
  • The most important form element is the <input> element.

 

Angular

All you need is the ngModel selector to activate it

 

Creates a FormControl instance from a domain model and binds it to a form control element.

Turning Dumb Input into a Smart one

<smart-input />

  • requires own html template (doing complex stuff like pipes and *ngIf *ngFor

<input smart-input />

Attribute directives attach behavior to elements.

An Attribute directive changes the appearance or behavior of a DOM element.

<!-- TYPESCRIPT -->
export const CUSTOM_LABEL_CONTROL_VALUE_ACCESSOR: any = {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => LabeledCheckbox),
    multi: true
};

@Component({
    selector: "labeled-checkbox",
    template: `
    <div class="checkbox">
      <input type="checkbox" [attr.id]="id" [(ngModel)]="model" [checked]="model" tabindex="{{tabIndex}}" [disabled]="disabled">
      <label [attr.for]="id">{{label}}</label>
    </div>
  `,
    providers: [CUSTOM_LABEL_CONTROL_VALUE_ACCESSOR]
})

<!-- HTML -->
<labeled-checkbox [label]="'Label 1'" [id]="'Label 1'" 
[(ngModel)]="checkboxModel"></labeled-checkbox>





<!-- TYPESCRIPT -->
export const CUSTOM_DATETIMEPICKER_CONTROL_VALUE_ACCESSOR: any = {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => DateTimePicker),
    multi: true
};

@Component({
    selector: "date-time-picker",
    template: `
    <div class="input-group date" #datetimepicker>
      <input type="text" [attr.id]="id" class="form-control" #input tabindex="{{tabIndex}}" (focus)="selectAll()"
      (blur)="_blurEvent($event)" placeholder="{{placeholder}}" />
      <div class="input-group-addon">
        <span class="fa fa-calendar"></span>
      </div>
    </div>
 `,
    providers: [CUSTOM_DATETIMEPICKER_CONTROL_VALUE_ACCESSOR]
})

<!-- HTML -->
<date-time-picker id="fromTime" 
[(ngModel)]="from" (blur)="blurEvent($event)"></date-time-picker>

Problems building smart-input with <Component />

@Component({
    selector: "date-time-picker",
    template: `
    <div class="input-group date" #datetimepicker>
      <input type="text" [attr.id]="id" class="form-control" #input tabindex="{{tabIndex}}" (focus)="selectAll()"
      (blur)="_blurEvent($event)" placeholder="{{placeholder}}" />
      <div class="input-group-addon">
        <span class="fa fa-calendar"></span>
      </div>
    </div>
 `
});

export class DateTimePicker {

    @Output() blur: EventEmitter<any> = new EventEmitter<any>();
    @Input() placeholder: string = this.service.shortDateTimeFormat;
    @Input() tabIndex: number;
    @Input() autofocus: boolean = false;
    @Input() id: string;
}

/*
if you have to configure one or more attributes, please consider to replace component to a directive
*/

Props V.S. Attributes

@Component({
    selector: "date-time-picker",
    template: `
    <div class="input-group date" #datetimepicker>
      <input type="text" [attr.id]="id" class="form-control" #input tabindex="{{tabIndex}}" (focus)="selectAll()"
      (blur)="_blurEvent($event)" placeholder="{{placeholder}}" />
      <div class="input-group-addon">
        <span class="fa fa-calendar"></span>
      </div>
    </div>
 `
});

export class DateTimePicker {

    @Output() blur: EventEmitter<any> = new EventEmitter<any>();
    @Input() placeholder: string = this.service.shortDateTimeFormat;
    @Input() tabIndex: number;
    @Input() autofocus: boolean = false;
    @Input() id: string;
}

<!-- HTML --> 
<date-time-picker id="fromTime" [(ngModel)]="from" (blur)="blurEvent($event)"></date-time-picker>

Invalid Duplicated <input id="" />

@Component({
    selector: "date-time-picker",
    template: `
    <div class="input-group date" #datetimepicker>
      <input type="text" [attr.id]="id" class="form-control" #input tabindex="{{tabIndex}}" (focus)="selectAll()"
      (blur)="_blurEvent($event)" placeholder="{{placeholder}}" />
      <div class="input-group-addon">
        <span class="fa fa-calendar"></span>
      </div>
    </div>
 `
});

export class DateTimePicker {

    @Output() blur: EventEmitter<any> = new EventEmitter<any>();
    @Input() placeholder: string = this.service.shortDateTimeFormat;
    @Input() tabIndex: number;
    @Input() autofocus: boolean = false;
    @Input() id: string;
}

<!-- HTML --> 
<date-time-picker id="fromTime" [(ngModel)]="from" (blur)="blurEvent($event)"></date-time-picker>

Difficult to support Form validation states

<date-time-picker required pattern="" [(ngModel)]="input"/>

<!-- trying to implement smarter-input as component, but form-validation is not supported! -->

<div class="form-group"
     [ngClass]="{'has-error': toDateTime.invalid && toDateTime.dirty && toDateTime.touched}">
    <date-time-picker [(ngModel)]="inputModel.to" required #toDateTime="ngModel"></date-time-picker>
</div>

FORM 

FORM-GROUP

FORM-CONTROL

FORM-GROUP

FORM-CONTROL

FORM-GROUP

FORM-CONTROL

<input smarter-input />

Extending native HTML inputs with Angular

By tlimpanont

Extending native HTML inputs with Angular

  • 795