I have three angular material based radio buttons namely male,female and other. So these three exist in a component.I also have three form fields namely A,B,C in another component named page1. When I press the male radio button and go to the page1 component the form field A and B in page1 component should not be visible. When I press female or other radiobutton all three form fields in page1 component should exist. I have tried for one day but nothing worked. Pls help if u know
Note:I am doing it using angular material(mat form field and mat radio button). In stackblitz I was unable to install those so pls do it in angular material way
I have attached a sample stackblitz link:
https://stackblitz.com/edit/angular-button-routerlink-mmn77s?file=src%2Fapp%2Fapp.component.html
you can use BehaviorSubject or Subject to trigger the function call
TriggerService.ts
import { Injectable } from "#angular/core";
import { BehaviorSubject } from "rxjs/internal/BehaviorSubject";
#Injectable()
export class TriggerService {
constructor() {}
private _trigger = new BehaviorSubject<string>("");
castTrigger = this._trigger.asObservable();
trigger(value) {
this._trigger.next(value);
}
}
parent.component.ts
export class AppComponent {
constructor(private triggerService: TriggerService) {
document.title = "Home";
}
changeType(value) {
this.triggerService.trigger(value);
}
}
child.component.ts
ngOnInit() {
this.triggerService.castTrigger.subscribe(value => {
this._type = value;
});
}
stackblitz example
Related
I have an application that has a list and details page. In the list page, the table has paging feature and there is also a search box that filters the list items. When clicking on an item in the list it opens details of the related record. I am wondering what is a proper way to keep the paging and filter parameters of the list page when I navigate to details page and then use these parameters when come back to this list page. I meant that, the user in on the 3rd page of the list and then click details icon of a record. then opens details page and later click back button on that page. I want the user can navigate to the 3rd page again by getting the parameter values that he sent before. If I can get these values the rest would be ok of course.
Should I use NavigationExtras or etc for this purpose?
There are multiple ways of implementing such functionality. In general, you need to save the last search state (search value, page, search results, etc.) somewhere during the list component OnDestroy and then use them in OnInit hook of the list component. Here's an example of using service:
list component
constructor(private preserveSearch: PreserveSearchService){}
ngOnInit() {
this.recoverLastSearchValue();
}
ngOnDestroy() {
this.preserveSearch.searchState = {
searchValue: this.searchControl.value,
results: this.data,
resultsLength: this.resultsLength,
};
}
recoverLastSearchValue() {
const lastSearch = this.preserveSearch.searchState;
if (lastSearch) {
this.searchControl.setValue(lastSearch.searchValue, {
emitEvent: false,
emitModelToViewChange: false,
});
this.data = lastSearch.results;
this.resultsLength = lastSearch.resultsLength;
}
}
search state service
import { Injectable } from "#angular/core";
import { SearchResultsItem } from "app/_models/search";
interface PreservedSearchState {
searchValue: string;
results: SearchResultsItem[];
resultsLength: number;
}
#Injectable({
providedIn: "root",
})
export class PreserveSearchService {
private lastSearch: PreservedSearchState;
get searchState(): PreservedSearchState {
return this.lastSearch;
}
set searchState(lastSearch: PreservedSearchState) {
this.lastSearch = lastSearch;
}
constructor() {}
}
I am not much familiar with Angular . I have a code where I am inputting some values using dropdown select
html 1:-
<angular-material-filter-dropdown
[dropdownList]="['Solid', 'Liquid', 'Gas']"
(selected)="triggerStateSelect($event)">
</angular-material-filter-dropdown>
Component 1:-
triggerStateSelect(event) {
console.log('state select ', event);
}
Here event stores the value.
HTML 2:-
<div class="title-container">
<p class="title">
{{}} -Dashboard
</p>
</div>
Now I want to pass selected value to a different component and also to display the selected in HTML
Whenever a value is selected , the second component must get the value and shows the value. Also when nothing is selected the second component must not show any previous selected value. It must get cleared.
How can I achieve this ?
You could use a service which provides you the Information with Observables. You create a service.ts file in which you declare your observable and observer. Everytime a value is selected you simply .next(value) in your service and then subscribe to it in the .ts file where you .html file is. Here is a good explanation on how to use Observables. I hope it helps
https://medium.com/#luukgruijs/understanding-creating-and-subscribing-to-observables-in-angular-426dbf0b04a3
If they have parent-child relationship you can interact via input
https://angular.io/guide/component-interaction#pass-data-from-parent-to-child-with-input-binding
If not, you can achieve it via service:
Create Service:
import { Observable, Subject } from 'rxjs';
#Injectable({ providedIn: 'root' })
export class SelectStateService {
private subject = new Subject<any>();
triggerStateSelect() {
this.subject.next();
}
onStateSelect(): Observable<any> {
return this.subject.asObservable();
}
}
Component 1:
constractor(private selectStateService : SelectStateService ){}
triggerStateSelect(event){
this.myService.triggerStateSelect(event);
}
Component 2:
constractor(private selectStateService: SelectStateService){}
state;
this.$subscription = this.selectStateService.onStateSelect().subscribe((event) => {
this.state = event;
}
);
ngOnDestroy() {
this.$subscription.unsubscribe();
}
Html 2:
<div class="title-container">
<p class="title">
{{state}} -Dashboard
</p>
</div>
documentation:
https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service
I am working on an Angular 4 application where I have one left panel and one right panel.
Apart from those panels I have 2 other components.
The left panel component contains buttons and the right panel component is currently empty.
What I want to do is when I click (for example), button 1 on the left panel component it loads a component inside the right panel component and so on.
It's the same as routing but I'm already using routing on my app.component for the top main menu so that's taken.
How do I go about doing this?
you may want to use a service to handle this.
Providing the service from the common parent component and injecting it inside the two components you will have a common poi for communication. at this point you can subscribe to some event in the right panel component of the service and raise it from the left calling a specific method:
this is an example of using events inside services
Here is a rough example of this kind of implementation.
import { Directive, ViewContainerRef } from '#angular/core';
#Directive({
selector: '[buttonView]'
})
export class ButtonViewDirective {
constructor(public viewContainerRef: ViewContainerRef) {}
}
import { ComponentFactoryResolver } from '#angular/core';
import { OneComponent, TwoComponent } from './components';
#Component({
selector: 'right-panel',
encapsulation: ViewEncapsulation.Emulated,
template: `
<div>
<ul>
<li *ngFor="let button of buttons">
<button (click)="onButtonClick(button)">{{button.name}}</button>
</li>
</ul>
</div>
<div>
<ng-template buttonView></ng-template>
</div>
`
})
class RightPanelComponent {
public buttons: any = [
{
name: 'Button 1',
component: OneComponent
},
{
name: 'Button 2',
component: TwoComponent
}
]
#ViewChild(ButtonViewDirective)
public buttonViewContent: ButtonViewDirective;
constructor(
protected _cmpFactoryResolver: ComponentFactoryResolver,
) {}
public onButtonClick(button: any): void {
this._createComponent(button);
}
private _createComponent(button: any): void {
if (button === null) {
return;
}
setTimeout(() => {
const cmpFactory = this._cmpFactoryResolver.resolveComponentFactory(button.component);
const viewContainerRef = this.buttonViewContent.viewContainerRef;
viewContainerRef.clear();
viewContainerRef.createComponent(cmpFactory);
});
}
}
The ButtonViewDirective is used like helper in our RightPanelComponent just to make much easier to bootstrap custom components: OneComponent, TwoComponent
The RightPanelComponent combines both panels the right and left one for this example. If you want to have them split then the right panel will have the logic of rendering and bootstrapping custom components and the left panel will have the logic of rendering button and trigger changes to the right side components. Communication between Right and Left can be made with an intermediate Service or some kind of events, observables implementation.
Here are some examples of implementation in the official angular doc.
https://angular.io/guide/dynamic-component-loader
I currently have this code in my app.component.ts
app.component.html
<div [ngClass]="myclass">
...rest of the content here
</div>
This I have the this:
<button (click)="changeClass('myFavClass')">Change Class to myFavClass</div>
app.component.ts
export class AppComponent {
myclass: string;
changeClass(myclass) {
this.myclass = myclass;
}
}
Now, all this works fine BUT I now want to put the triggering button on another component.
If I put this on another component:
<button (click)="changeClass('myFavClass')">Change Class to myFavClass</div>
How can I get it to change the class?
There are two ways you can do this you can use output with an EventEmit
Or you can set up a service that monitors the changes to a variable and use that as the control point for the change.
Personally, I use services for this instance as its easier to manage the code and its flow.
This answer has all the code in you need to look at.
Changing a value in two different components at the same time Angular 2
Hope that helps
There are at least two options. Subject and Observable or if this another component is a parent you can use #Input.
Subject and Observable method:
angular guide Highly recommended to read whole page.
Some component
export class SomeComponent {
constructor(private ClassService: ClassService) { }
private changeClass(class) {
this.ClassService.changeClass(class);
}
}
Another Component
export class AnotherComponent implements OnInit, OnDestroy {
constructor(private ClassService: ClassService) { }
private class: string = "";
private subscribtion: Subscribtion;
ngOnInit(): void {
this.Subscribtion = this.ClassService.someClass$.subscribe(
(class) => { this.class = class; }
)
}
ngOnDestroy(): void {
this.Subscribtion.unsubscribe();
}
}
Service
#Injectable();
export class ClassService{
constructor() { }
private someClassSource= new Subject<string>();
someClass$= this.someClassSource.asObservable();
changeClass(class) {
this.someClassSource.next(class);
}
}
taken from my answer
#Input method:
angular guide
This is very simple, when you click button changeClass method will change elClass which will be passed to another component by #Input decorator, every change of #Input will cause a detect changes which will detect that value has changed so class will change to myClass.
Parent component
parent.component.html
<another-component [elementClass]="elClass"></another-component>
<button (click)="changeClass('myClass')">change class<button>
parent.component.ts
export class ParentComponnet {
private elClass: string = "";
changeClass(class: string) {
elClass = class;
}
}
Another component (must be child component)
another.component.html
<div [ngClass]="elementClass">
another.component.ts
export class AnotherComponent {
#Input() elementClass: string;
}
There is also Child to Parent interaction via #Output (emitting event) angular guide
Could you please suggest how to add item in list when something enter in input field and then enter press.But these are different component .I want to share input field value to different component using #Input ,#Output ,EventEmitter.
I make one component .
<todo></todo>
here is ts file
import { Page,NavController,Modal } from 'ionic-angular/index';
import { Component, Input, Output, EventEmitter} from 'angular2/core';
#Component({
selector:'todo'
templateUrl:"addtodo.html",
})
export class AddToDO{
constructor() {
}
addItem(v){
alert(v.value)
}
}
here is my html
<label class="item item-input">
<span class="input-label" >Add Todo</span>
<input type="text" #todo placeholder="Add todo" (keyup.enter)="addItem(todo)">
</label>
I want to add item list when enter is press .so need to share data between component
http://plnkr.co/edit/N6aXDZXUr99MC6w77H6d?p=preview
I would leverage an #Output in your AddToDO component to trigger that an element was added. So you can catch it from the parent component and add the corresponding data in the list.
#Component({
selector:'todo'
templateUrl:"addtodo.html",
})
export class AddToDO{
#Output()
todoAdded:EventEmitter = new EventEmitter();
constructor() {
}
addItem(v){
alert(v.value)
this.todoAdded.emit(v);
}
}
and in the parent component template:
<todo (todoAdded)="addTodoInList($event)"></todo>
Here is the content of the addTodoInList method:
addTodoInList(todo) {
this.Todo.push(todo);
}
See this plunkr: http://plnkr.co/edit/mQtQIXIJwMfJSfNVHvac?p=preview.