#Host() without <ng-content> in Angular2 not working - javascript

I'm trying to limit the search of my dependencies to only its host by using #Host.
But it's not working without ng-content or transclusion.
The below code is not working(without ng-content)
// Root Component
#Component({
selector: 'my-app',
template: '<parent></parent>'
})
export class RootComponent { }
#Component({
selector: 'parent',
template: '<child></child>',
providers:[{provide:TestService,useClass:TestService}]
})
export class ParentComponent {
name: string = '';
constructor(abc:TestService){
abc.name='SomeName';
this.name=abc.name
}
}
#Component({
selector: 'child',
template: '<h1>{{parent}}</h1>'
})
export class ChildComponent {
parent: string = ""
constructor(#Host() testService: TestService) {
this.parent= 'My parent is :'+testService.name;
}
}
With ng-content
Now just by changing the templates in RootComponent & the ParentComponent the above code starts working
#Component({
selector: 'my-app',
template: '<parent><child></child></parent>'
})
export class RootComponent { }
#Component({
selector: 'parent',
template: '<ng-content></ng-content>',
providers:[{provide:TestService,useClass:TestService}]
})
export class ParentComponent {
name: string = '';
constructor(abc:TestService){
abc.name='SomeName';
this.name=abc.name
}
}
#Component({
selector: 'child',
template: '<h1>{{parent}}</h1>'
})
export class ChildComponent {
parent: string = ""
constructor(#Host() testService: TestService) {
this.parent= 'My parent is :'+testService.name;
}
}
Questions:
Why the first code not working(without ng-content)..?
#Host can only works with ng-content..?
What difference ng-content makes as the structure of the compiled HTML is same in both the cases.
Here are the Plunker for reference:
Not working

It looks like you need to use viewProviders instead of providers to work with #Host as also shown in #Host
Plunker example

Related

Angular component comuniaction

I need help about angular component comunication.
I have Parent component and children.
In parent component i have list. I would like to click of item list and move data {name, text} to children component and set it to children component where is froala editor.
In Angular, there are two ways you can do implement component intercommunication.
Pass data from parent to child with input binding
#Component({
selector: 'app-parent',
template: `
<app-child [childMessage]="parentMessage"></app-child>
`,
styleUrls: ['./parent.component.css']
})
export class ParentComponent{
parentMessage = "message from parent"
constructor() { }
}
#Component({
selector: 'app-child',
template: `
Say {{ message }}
`,
styleUrls: ['./child.component.css']
})
export class ChildComponent {
#Input() childMessage: string;
constructor() { }
}
Using Angular Services(This method is used when the components communicating are directly related ). But from you are describing you can do it better with angular service. When you click the item list, you can call the function of services that pushes the data to the BehaviourSubject. After that, all the component that are subscribed to that Behaviour subject will get the data you passed.
#Injectable()
export class DataService {
private messageSource = new BehaviorSubject('default message');
currentMessage = this.messageSource.asObservable();
constructor() { }
changeMessage(message: string) {
this.messageSource.next(message)
}
}
import { Component, OnInit } from '#angular/core';
import { DataService } from "../data.service";
#Component({
selector: 'app-parent',
template: `
{{message}}
`,
styleUrls: ['./sibling.component.css']
})
export class ParentComponent implements OnInit {
message:string;
constructor(private data: DataService) { }
ngOnInit() {
this.data.currentMessage.subscribe(message => this.message = message)
}
}
import { Component, OnInit } from '#angular/core';
import { DataService } from "../data.service";
#Component({
selector: 'app-sibling',
template: `
{{message}}
<button (click)="newMessage()">New Message</button>
`,
styleUrls: ['./sibling.component.css']
})
export class SiblingComponent implements OnInit {
message:string;
constructor(private data: DataService) { }
ngOnInit() {
this.data.currentMessage.subscribe(message => this.message = message)
}
newMessage() {
this.data.changeMessage("Hello from Sibling")
}
}

Pass data from parent component to child component using #input decorator in angular 8

Hello i want to pass a number from component to another and i'm using #input.
Here my parent component :
#Component({
selector: 'inter-asp',
styleUrls: [('./asp.component.scss')],
templateUrl: './asp.component.html',
template: '<app-my-dialog [hellovariable]="hellovariable"></app-my-dialog>',
providers: [PaginationConfig],
})
export class aspComponent implements OnInit {
public hellovariable: number = 100;
}
and here my child component :
#Component({
selector: 'app-my-dialog',
templateUrl: './my-dialog.component.html',
styleUrls: ['./my-dialog.component.css']
})
export class MyDialogComponent implements OnInit {
#Input() hellovariable: number;
}
in the child component i want to show the content of my variable hellovariable passed from parent component but i get undefined it is not passed so what is the problem here.
In the parent template you have to pass the input to the child as a property of the child component
<app-child-component [prop]="prop"></app-child-component>
It takes preference to the template url, remove that part and have it as
#Component({
selector: 'inter-asp',
styleUrls: [('./asp.component.scss')],
template: '<app-my-dialog [hellovariable]="hellovariable"></app-my-dialog>',
providers: [PaginationConfig],
})
STACKBLITZ DEMO

Angula2 input not binding

I am trying to bind some data but is not working on
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
template : `<child [in]="25"></child>`
})
export class AppComponent {}
and the child component
import { Component, Input } from '#angular/core';
#Component({
selector: 'child',
template: '<h1>{{in}}</h1>',
})
export class ChildComponent {
#Input() in: string;
}
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
template : <child [in]="25"></child>
})
export class AppComponent {}
import { Component, Input } from '#angular/core';
#Component({
selector: 'child',
template: '{{in}}',
})
export class ChildComponent {
#Input() in: string;
}
Nothing wrong in this code .. every thing is working fine.
You have two ways of assigning values to an input of a component:
1) Either by passing directly the string value to the input from the template:
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
template : `<child in="25"></child>`
})
export class AppComponent {}
2) Or by binding the input to a variable defined in your class:
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
template : `<child [in]="myVar"></child>`
})
export class AppComponent {
public myVar: string = "25";
}
As a result you cannot bind the input to a numeric variable as you did here, simply because a variable defined in a class cannot be numeric (but it surely can be alphanumeric).
You should actually assign a variable and then refer it. public Hello = "25";
Then [in]="this.hello"
OR
Remove the brackets and assign directly
in ="25";

Is there a way to load template URL of the component passed as #Input in Angular 2?

I have a simple component as follows:-
#Component({
selector: 'list',
templateUrl: './list.component.html',
styleUrls: ['./list.component.css']
});
export class listComponent implments onInit {
#Input customTemplateUrl: string;
}
Can I load the custom template passed as #Input as the template for the component?

angular2 Multiple level children routes for same router-outlet

#angular/router
Is there a way to have different routes with different levels all populating int he same router-outlet of that parent?
example:
/a/b/c/d
/a/b/c
/a/b
all populating in the router-outlet of component a ?
Thanks,
you can do it , you just have to maintain the routes in correct order,
Like below see a/b/c comes before a/b, means fully qualified path should come first.
export const routes: RouterConfig = [
{ path: 'a/b/c', component: ABC },
{ path: 'a/b', component: AB }
];
#Component({
selector: 'my-app',
template: `
<h1 class="title">Component Router</h1>
<nav>
<a routerLink="/a/b" routerLinkActive="active">a/b</a>
<a routerLink="/a/b/c" routerLinkActive="active">a/b/c</a>
</nav>
<router-outlet></router-outlet>
`,
directives: [ROUTER_DIRECTIVES]
})
export class AppComponent {
}
#Component({
selector: 'my-abc',
template: `
<h1>a-b-c</h1>
`
})
export class ABC {
}
#Component({
selector: 'my-ab',
template: `
<h1>a-b</h1>
`
})
export class AB {
}
Here is the Plunker!

Categories