Andrii Albu
Andrii Albu

Reputation: 63

Manually inject service into directive from component

I have directive

     @Directive({
      selector:'[appAsyncNameValidator][formControlName],[appAsyncNameValidator][ngModel]',
      providers: [
        {
          provide: NG_ASYNC_VALIDATORS,
          useExisting: forwardRef(() => AsyncNameValidatorDirective), multi: true
        }
      ]
    })

    export class AsyncNameValidatorDirective implements Validator {
       constructor(private service: any service that implements IForValidation) {
       }

      validate(c: AbstractControl): Observable<any> {
         return doSomethig(c); // => use in doSomethig service.getByName(c.value) 
      }
    }

export interface IForValidation{
       getByName(name: string);
    }

And component

@Component({
  selector: 'app-edit-role',
  template: `<input type="text" class="form-control" id="roleName" name="roleName" 
             placeholder="Role name..." [(ngModel)]="role.name" appAsyncNameValidator 
             required #roleName="ngModel">`,
  styleUrls: ['./edit-role.component.scss']
})

export class EditRoleComponent implements OnInit {
    constructor() {
    }
}

And I want to make this directive generic for all services. How to inject any service into directive from component ?

Upvotes: 2

Views: 1887

Answers (2)

George Stocker
George Stocker

Reputation: 57907

Edit

I've added next inputs to my directive

@Input() service: any;

@Input() methodName: string;

And used it like this in my doSomethig(c) method:

this.service[this.methodName](value);

In component you have to use it in next way:

<input type="text" class="form-control" id="roleName" name="roleName" placeholder="Role name..." 

          [(ngModel)]="role.name" appAsyncNameValidator [service]="roleService" [methodName]="'methodName'"

          required #roleName="ngModel">

Hope this will help somebody.

Upvotes: 1

Michael Kang
Michael Kang

Reputation: 52867

You could define an interface IRoleService:

export interface IRoleService {
    getRoles(uid:string):Role[];
    ...
}

const IRoleService = new OpaqueToken("IRoleService");

Setup the binding of your interface to a concrete class:

@NgModule({
    providers: [{
         provide: IRoleService,
         useClass: RoleService
    }]
})

Inject it like this:

constructor(@Inject(IRoleService) roleService:IRoleService).

Upvotes: 1

Related Questions