How to nest data to child>child>child component? - javascript

I have a structure:
Root component
buttons
(menu search component) - a simple input field
Widgets
(widget component )
(Cats widget) - displays what I put in menu search here.
How I pass data from menu search component to widget component?
User insert data in input field and I would like to displat in the widget field.
Do I have to call the event emitter from menu search and pass the data to buttons, and than go done widgets>Widget Child> cats component to display?
If so how do I correct pass the data? Espciall how do I pass the data downwards?
What I've currently done is used #Output to pass the data from cats to widgets, from widgets to root app.
To pass from child event I did
#Output() inputData: EventEmitter<string> = new EventEmitter<string>();
customFunction(event){
this.inputData.emit(event);
}
Than on the parent catch the event
<cats (inputData)="colorChange($event)"></cats>
until I reached Root component.

The angular guide has a bunch of tips around handling various component to component data interaction scenarios like this one.
The basic options are to chain property and output bindings between the intermediate components, use dependency injection and ViewChild decorators to 'jump' the view hierarchy and grab instances of your 'higher level' components from lower ones (dependency injection) or vice versa (ViewChild), or the use of services to pass data around (probably the best option in more varied situations due to less coupling to the view hierarchy).
See the angular docs for more info.

Related

Pass data to other page/component in Angular

I have my user input as below in my html file:
<div class="form-group col-md-4">
<label for="btsIp"><strong>BTS IP:</strong></label> <input ngModel type="text"
name="btsIp" class="form-control" id="btsIp" (blur)="onChange()" [(ngModel)]="btsIp">
</div>
In my component.ts i am using it as
btsIp: any and passing it in my request
let Data = {
"btsIp": this.btsIp
}
which is working fine. But i want to pass this btsIp value to another page/Component where i need to call a request again where i need to pass the same btsIp value.
Could you all please help?
Passing data to the other page/component, it depends on whether it's the parent component, a sibling component, or a completely unrelated component in a different route.
Parent component: you can trigger a parent's component function by hooking on the #Output of the child component. Or you can access child component's properties via #ViewChild declaration. Read more: https://angular.io/guide/component-interaction
Sibling component: first transfer to the parent component as describe above, then pass the data from parent to child component via child's #Input.
A completely different page in a different route: you can pass the data via route params. Read more: https://angular.io/guide/router
Other approach: if you can afford using NgRx (state management inspired by Redux powered by RxJs for Angular), everything will be much easier once you mastered it, but that's a huge other topic that cannot be included in this answer box. More at https://github.com/ngrx/platform
Create a new ts File, inject that in to your module, use get and set
get IP (){
return this.btsIp;
}
set IP (btsIp){
this.btsIp= btsIp;
}
Hope it would help

At what point in an Angular2 parent/child component hierarchy should you subscribe to an observable?

I have 18 directives all picking apart a very large Object that the parent component is subscribed to (not http). Do I dole out the properties to the different directives or would it be better instead to pass the observable and let the varying components subscribe to only the properties they need.
In short, should I:
Pass an observable to angular2 directives and subscribe from within the directive component
Subscribe in the parent and pass the resulting data of observable to angular2 directives. (This is how I currently have it implemented)
With Angular2 and component tree structure comes a pattern that you should use : Dumb and Smart components.
A Smart component can register to anything you want and have some logic in it
A Dumb component on the opposite is supposed to be used only to display a view with some data (passed as Input)
A really simple example would be :
PersonComponent : A dumb component should display a person (let say name and age)
<div>
Hi, my name is {{person.name}} and I'm {{person.age}} years old !
</div>
PeopleComponent : A smart component which calls PeopleService to get a list of user. It then subscribe to the response (which is an Observable). His view should display the list of person like that :
<person *ngFor="let p of people" [person]="p"></person>
And let say that you don't even really need to subscribe to your observable within your TS file, then you could use the async pipe from Angular2 :
<person *ngFor="let p of (people | async)" [person]="p"></person>
The important thing is that PersonComponent will not receive (neither in the first nor the second solution) an Observable. It's just a dumb component which has to display data when needed (when the observable receive at least one response from the server).

Golden Layout + Angular2 RC5 - Unable to use ViewContainerRef to dynamically create component

I am trying to dynamically create the component to register in Golden Layout. Eg,
#ViewChild('placeholder', { read: ViewContainerRef }) viewContainerRef;
ngAfterViewInit(){
this.myLayout.registerComponent('testComponent', (container, componentState) => {
//Create an empty div on the container
container.getElement().html("<div #placeholder></div>");
this.componentFactory = this.componentFactoryResolver.resolveComponentFactory(TestComponent);
this.cmpRef = this.viewContainerRef.createComponent(this.componentFactory);
this.cmpRef.changeDetectorRef.detectChanges();
GlDirective.componentCount++;
});
}
However , because viewContainerRef is referring to ViewChild that only gets created now , it is always undefined. How can we create a component in RC5 that uses dynamically added div like the one above. I used #Günter Zöchbauer 's answer on Angular 2 dynamic tabs with user-click chosen components to derive to this. However unsure on how this can be achieved with Golden Layout which needs the DOM to be generated on the fly. Please help.
This is not supported.
Something like #placeholder in
container.getElement().html("<div #placeholder></div>");
will just be added to the browser and not recognized or processed in any way by Angular2 (except sanitization for security purposes).
A template variable can only be created by adding it statically to a components template.

Component communication in angular 1.5

Angular 1.5 component communication suggestions usually have output bindings to invoke methods on root controllers.
Let's say I have a root component, and two child components.
<root>
<child-1></child-1>
<child-2></child-2>
</root>
It'd like to react to a button click on component one by reading a value on component two and then doing something in the root.
For example, child-1 is a directive which wraps a drawing library that attaches a drawing to its DOM node and has a variable to control that drawing.
child-2 has a button. When it is clicked, data from the child-1 variable should be passed on to root which does something with it.
Specifically, child-1 wraps var graph2d = new vis.Graph2d(container, dataset, options);. Later on, I would like to retrieve some information from graph2d and pass it on to root to do something with it.
This boils down to: how can components react to events issued by other components? The inputs and outputs suggestions don't seem to cover that scenario.
In angular 1.5 you can use require and/or property bindings (input/output) to communicate.
If you use the require property then your root component would publish an api and your child component would get a reference to the controller:
angular.module('app').component('child1', {
bindings: {},
require: {api: '^root'}, //your <root> component
template: '',
controller: controller
});
You can then use the methods of the root component in your child component:
$ctrl.api.addWatchedBook();
This is the root component controller function:
$ctrl.addWatchedBook = addWatchedBook;
function addWatchedBook(bookName){
booksWatched.push(bookName);
}
Here is a complete architectual overview: Component Communications

ExtJs5: Call Controller 2's method from Controller 1

I am trying my hands on the new ExtJs 5.
I have created a small app as per the defined MVC pattern of ExtJs5.
Am using ViewControllers for each View.
Problem Statement: Now suppose I have two VCs (Controller1 & Controller2). Each has its own methods. I wish to call a method of Controller2 from Controller1. I want to update the View associated with the Controller2 from Controller1.
E.g. Suppose there is a separate view for Status Bar and a ViewController(StatusBarController).
This VC has a method to update the view based on whatever message it receives as input parameter.
All the other controllers in the application will call this VCs method to update the status of the application on the status bar.
In the previous versions, this.getController('StatusBarController') was used to get the handle to any controller and then call its method.
But this is not working in my case when I use a ViewController.
Can anyone guide me how to achieve this thing? And also whether it is the correct/ideal way to do such a thing or is there any better option?
Here is my code:
StatusBarView:
Ext.define('MyApp.view.statusbar.StatusBarView', {
extend : 'Ext.panel.Panel',
controller: 'StatusBarController',
region : 'south',
xtype : 'status-bar-panel',
html : 'This is a status bar'
});
StatusBarController:
Ext.define('MyApp.controller.StatusBarController', {
extend : 'Ext.app.ViewController',
alias: 'controller.StatusBarController',
updateStatusBar : function(message) {
this.getStatusBarView().update(message);
}
});
Some Other Controller in app:
Ext.define('MyApp.controller.ResourcesPanelController', {
extend : 'Ext.app.ViewController',
alias : 'controller.ResourcesController',
onItemClick : function(tree, record, item, index, e, eOpts) {
// here I am calling the other controller's method.
this.getController('StatusBarController').updateStatusBar(
record.data.text + ' has been clicked');
}
});
ViewControllers are tightly related to their views, they are even created and destroyed together with views, and they should be controlling only their own views. The idea is to separate logic from UI on the view level.
Calling methods of one ViewController from another is not a good practice and, for big applications, it is route to hell as it inevitably leads to unmaintainable spaghetti code.
The correct approach is minimize the number of ViewModels, ViewControllers and Controllers and let them work in their own areas of responsibilities.
For example: Suppose you want a grid and form in a container. Form would allow editing of the record selected in the grid. Plus some buttons. These three views (container, grid and form) together form a unit. Thus:
only one ViewController at container is needed, all views can use it
only one ViewModel at container is needed, all view can use it
if you want to let this trio to communicate with the outer world of the rest of the application, the container's view controller can fire events and can have API methods to call
Thus, if needed, you can have an MVC (global) Controller(s) that would coordinate functions of units, like our trio.
Also, data binding simplifies the logic to a great degree so controllers and listeners are not needed that much.
See Binding Grid and Form in ExtJS 5 example.
my answer is simple and short:
Ext.app.ViewController.fireEvent()
while one can add any type of custom event with the listeners config of the ViewController - the docs of the listen config state "event domains", so I'd assume, that both controller need to reside within the same domain in order to be able to interact, event-wise.
the 2nd argument of .fireEvent() might need to imitate the element which ordinary triggers the event.
well, it should also be possible to access it like that (in the secondary controller):
this.getApplication().getStatusBarController().updateStatusBar('...');

Categories

Resources