How to reuse the component - html

Factor is a component and Idea is an another component I need to show all the data's of Factor in the Component Idea.Can anyone say How to reuse the component.

You need to use #Input() for passing data into child component, and #Output() for emitting event from child component. You can refer to the documentation for more clarity https://angular.io/guide/inputs-outputs

you creat a component like :
ng g component xyz
after using selector reuse component Like
=> <app-xyz(component-Name)></app-xyz(component-Name))

Related

How to add or remove CSS class of an external library component from our own component in Angular

I have a component which has an external library component. I want to change toggle one class of external library component based on some condition in my own component. Here thus, I can not use ngClass. I could use document.querySelector but I dont want to use it. Is there any other way?
You can use ViewChild in your component class to reference the external library component, configuring ViewChild's read option to give you the component as an ElementRef so you can then toggle the DOM element class.
For example, if the external component in your component's template looks like this:
<div>
<external-component class="toggle-me"></external-component>
</div>
You can attach a template reference variable to it, like so:
<div>
<external-component #exComp class="toggle-me"></external-component>
<!-- ^^ add this template reference variable -->
</div>
Then in your component class, use ViewChild to get a hold of the external component using that template reference variable, specifying { read: ElementRef } so you get its DOM element rather than its component class instance:
#ViewChild('exComp', { read: ElementRef }) externalComponent: ElementRef;
With that, you can then access the nativeElement and its classList to toggle the class:
this.externalComponent.nativeElement.classList.toggle('toggle-me');
Alternatively, if you didn't want to add a template reference variable, or were not able to, you could pass the external component's class name, rather than the template reference variable name, to ViewChild.
#ViewChild(ExternalComponent, { read: ElementRef }) externalComponent: ElementRef;
Here's a StackBlitz showing both options.

Passing label value from HTML to TS

I have a code that goes something like this :
<sh-toggle label='ABCD' id = 'ABCD'> </sh-toggle>
I want to extract the value of label in TS file. Please tell me how it can be done? If i am trying document.getElementByID('ABCD'), then i am getting whole toggle component and unable to filter label from there.
Please mind sh-toggle is a custom tag.
You can use viewchild query to fetch a child component.
Create a template reference variable(#el) for the component / element you want to query.
<sh-toggle label='ABCD' id='ABCD' #el></sh-toggle>
Use viewchild query to fetch the child component. It looks for the first element that matches the selector.
#ViewChild('el', { read: ElementRef }) el: ElementRef;
ngAfterViewInit(): void {
console.log('label', this.el.nativeElement.getAttribute('label'));
}
If sh-toggle is your own directive (e.g.: ToggleDirective) then you can access its properties by #ViewChild:
considering you have a label #Input within ToggleDirective
add #ViewChild(ToggleDirective) toggle:ToggleDirective;
then simply anywhere from .ts just toggle.label
This is an angular way to access a component property.
document.getElementByID is never the angular way.
Stackblitz example
I'm not sure if you are using any frameworks/libraries on the UI side.
Just see if this code is enough
document.getElementById("ABCD").attributes.getNamedItem("label").value

How to handle multiple subscriptions on the same subject?

I have following scenario: I have child components, Component A and Component B, who listen on the same Subject from an external service, like this:
this.externalService.outcome.subscribe((event)=>{
event.preventDefault();
if(event.id === "SAVE"){
// Do something individudal...
this.externalService.save();
}
})
Basically I am intercepting the outcome Subject, do something specific for the current component and then manually trigger the save action.
Now having this piece of code in multiple components can get messy and can lead to errors. I need this subscription in all of my components, because each of them does something individual.
How can I refactor this, so that a parent component/ a shared service class manages all the subscriptions? So for example in the child components I just define a method what should be done and then I subscribe to the externalService.outcome in my parent component/ shared service and basically execute all registered functions?
EDIT: The thing is I also need the context of the current child component.
EDIT2: To sum it up this should be the sequence:
External Service (Library) calls outcome.next()
--> My Parent component who listens to the outcome Subject intercepts:
this.externalService.outcome.subscribe((event)=>{
event.preventDefault();
if(event.id === "SAVE"){
//SOMEHOW ENSURE ALL CHILD COMPONENTS ARE TRIGGERED
}
//manually trigger save outcome
this.externalService.save();
});
--> Inside the subscription I somehow need to trigger my child components. For example every childcomponent has a method "domeSomethingBeforeSave()". But I don't know my childcomponents so I need to define some kind of registerfunction to tell my parent component, which functions should get called.
Looking into the problem one of the solution could be:
Subscribe at the parent component and create input property in all of the child component for passing the data.
Then on ngOnChanges event of each child component do the stuffs you want to.
You can create a shared parent service to inject into both parent and child component for things to happen
// sharedService with external service injected
// you can take interceptor function as an param
this.onSave=(interceptor)=>this.externalService.outcome.pipe(filter(event=>event.id === "SAVE"),
map(res=>interceptor(res))
)
In your parent or child component you can always hook up to these observable to do what ever you want
// pass in interceptor
this.sharedService.onSave(doSomethingBeforeSave).subscribe()

Accessing HTML field of Parent Component in Library's component

I have created an Angular 6 library using 'ng generate library' command. This library is used in my base component after --prod build and then importing in app.module.ts of main application. The ...Component file in Library has #Input("leftPanel") leftPanel: ElementRef;
HTML Div element on base.component.html is like this: <div #leftPanel></div>
And the library element using its selector :
<lib-ng-mylibrary [leftPanel]="leftPanel"> </lib-ng-mylibrary>
Library component implements AfterViewInit. In the implementation method, this code execution fails: this.leftPanel.nativeElement.style.flexBasis = '50%';
it says, this.leftPanel.nativeElement is undefined. But i can see this.leftPanel point to the div. Wonder why it does not allow this.leftPanel.nativeElement` even tho #Input leftPanel is of type 'ElementRef'?
Thanks in Advance!
Harshad
Instead of sending the parent ElementRef my feeling is that your component should have and #Output and trigger an event handled by the parent, to change the native panel width.
Doing like you reduce the coupling between the object and make them more reusable.
See docs here: https://angular.io/guide/component-interaction
Still want to use ElementRef as parameter
If you still want to send the leftPanel as a parameter, you will need an #Input() variable in your main component as well, so it can resolve <div #leftPanel> to a local variable and that variable be used in [leftPanel]="leftPanel"
cheers

Pass data from nested Components Angular 2

I have a component where with a *ngFor print some boxes defined in an other component like this:
<div>
<commponentB *ngFor="let a of list"></componentB>
</div>
where "list" is a list ok object like this:
this.list=[{"id":"3","nome":"app3","posizione":3},{"id":"1","nome":"app1","posizione":1},{"id":"2","nome":"app2","posizione":2}];
I have to populate all the component. How can I transfer data from this two component?
TY
EDIT1:
the problem is that the list is splitted into 2 list for the repeat in 2 different bootstrap columns so the situation is this:
<div>
<commponentB *ngFor="let a of list1"></componentB>
</div>
<div>
<commponentB *ngFor="let a of list2"></componentB>
</div>
and the component is like that:
<div>
<span>{{name}}</span>
</div>
if I pass all the list I can't know how to populate the component at the right position (sorry if I don't explain the problem very well)
Since your components are directly linked, you can use the #Input() component interaction to send data from the parent to the child.
Here is a link from the official documentation :
https://angular.io/guide/component-interaction#pass-data-from-parent-to-child-with-input-binding
If you can't do that model because of a router interaction, or components are too "far" away so it's too much work to setup several inputs, you can use a shared service to share the data from one to another component.
https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service
if you want to pass your list to componentB you can define Input() property in componentB and then pass your list
<div>
<commponentB [list]="list"></componentB>
</div>
export class ComponentB{
#Input() list: any[];
}
Update Ok maybe I'm not getting your issue, even if you have to pass different inputs to same component you can do that. Check out this plunker: