How to pass multiple parameter to @Directives (@Components) in Angular with TypeScript?

JavascriptAngularTypescriptAngular6

Javascript Problem Overview


Since I've created @Directive as SelectableDirective, I'm little bit confused, about how to pass more than one value to the custom directive. I have searched a lot but didn't get proper solution in Angular with Typescript.

Here is what my sample code is:

Parent Component as MCQComponent:

import { Component, OnInit } from '@angular/core';
import { Question } from '../question/question';
import { AppService } from '../app.service/app.service';
import { SelectableDirective } from '../selectable.directive/selectable.directive';
import { ResultComponent } from '../result-component/result.component';

@Component({
	selector: 'mcq-component',
	template: "
	     .....
		<div *ngIf = 'isQuestionView'>
			<ul>
				<li *ngFor = 'let opt of currentQuestion.options' 
					[selectable] = 'opt'
					(selectedOption) = 'onOptionSelection($event)'>
					{{opt.option}}
				</li>
			</ul>
			.....
		</div>

	"
	providers: [AppService],
	directives: [SelectableDirective, ResultComponent]
})
export class MCQComponent implements OnInit{
	private currentIndex:any = 0;
	private currentQuestion:Question = new Question();
	private questionList:Array<Question> = [];
    ....
	constructor(private appService: AppService){}
	....
}

This is a parent component having custom directive [selectable] which takes one param called opt.

Here is the code for this directive:

import { Directive, HostListener, ElementRef, Input, Output, EventEmitter } from '@angular/core'
import { Question } from '../question/question';

@Directive({
	selector: '[selectable]'
})
export class SelectableDirective{
	private el: HTMLElement;
	@Input('selectable') option:any;
	
	...
}

So here I want to pass more parameters from parent component, how do I achieve this?

Javascript Solutions


Solution 1 - Javascript

From the Documentation

> As with components, you can add as many directive property bindings as > you need by stringing them along in the template. > > Add an input property to HighlightDirective called defaultColor: > > @Input() defaultColor: string;

Markup

>

> Highlight me too! >

> > Angular knows that the defaultColor binding belongs to the HighlightDirective because you made it public with the @Input > decorator. > > Either way, the @Input decorator tells Angular that this property is > public and available for binding by a parent component. Without > @Input, Angular refuses to bind to the property.

For your example

With many parameters

Add properties into the Directive class with @Input() decorator

@Directive({
    selector: '[selectable]'
})
export class SelectableDirective{
    private el: HTMLElement;

    @Input('selectable') option:any;   
    @Input('first') f;
    @Input('second') s;

    ...
}

And in the template pass bound properties to your li element

<li *ngFor = 'let opt of currentQuestion.options' 
    [selectable] = 'opt' 
    [first]='YourParameterHere'
    [second]='YourParameterHere'
    (selectedOption) = 'onOptionSelection($event)'>
    {{opt.option}}
</li>

Here on the li element we have a directive with name selectable. In the selectable we have two @Input()'s, f with name first and s with name second. We have applied these two on the li properties with name [first] and [second]. And our directive will find these properties on that li element, which are set for him with @Input() decorator. So selectable, [first] and [second] will be bound to every directive on li, which has property with these names.

With single parameter

@Directive({
    selector: '[selectable]'
})
export class SelectableDirective{
    private el: HTMLElement;

    @Input('selectable') option:any;   
    @Input('params') params;

    ...
}

Markup

<li *ngFor = 'let opt of currentQuestion.options' 
    [selectable] = 'opt' 
    [params]='{firstParam: 1, seconParam: 2, thirdParam: 3}'
    (selectedOption) = 'onOptionSelection($event)'>
    {{opt.option}}
</li>

Solution 2 - Javascript

to pass many options you can pass a object to a @Input decorator with custom data in a single line.

In the template

<li *ngFor = 'let opt of currentQuestion.options' 
                [selectable] = 'opt'
                [myOptions] ="{first: opt.val1, second: opt.val2}" // these are your multiple parameters
                (selectedOption) = 'onOptionSelection($event)' >
     {{opt.option}}
</li>

so in Directive class

@Directive({
  selector: '[selectable]'
})

export class SelectableDirective{
  private el: HTMLElement;
  @Input('selectable') option:any;
  @Input('myOptions') data;
  
  //do something with data.first
  ...
  // do something with data.second
}

Solution 3 - Javascript

Another neat option is to use the Directive as an element and not as an attribute.

@Directive({
   selector: 'app-directive'
})
export class InformativeDirective implements AfterViewInit {

    @Input()
    public first: string;

    @Input()
    public second: string;

    ngAfterViewInit(): void {
       console.log(`Values: ${this.first}, ${this.second}`);
    }
}

And this directive can be used like that:

<app-someKindOfComponent>
    <app-directive [first]="'first 1'" [second]="'second 1'">A</app-directive>
    <app-directive [first]="'First 2'" [second]="'second 2'">B</app-directive>
    <app-directive [first]="'First 3'" [second]="'second 3'">C</app-directive>
</app-someKindOfComponent>`

Simple, neat and powerful.

Solution 4 - Javascript

Similar to the above solutions I used @Input() in a directive and able to pass multiple arrays of values in the directive.

selector: '[selectorHere]',

@Input() options: any = {};

Input.html

<input selectorHere [options]="selectorArray" />

Array from TS file

selectorArray= {
  align: 'left',
  prefix: '$',
  thousands: ',',
  decimal: '.',
  precision: 2
};

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSagar GaneshView Question on Stackoverflow
Solution 1 - JavascriptSuren SrapyanView Answer on Stackoverflow
Solution 2 - JavascriptilDugView Answer on Stackoverflow
Solution 3 - JavascriptAharon OhayonView Answer on Stackoverflow
Solution 4 - JavascriptDeepakView Answer on Stackoverflow