set and get data from service angular 5 - javascript

I am using angular 5
my scenario is from one component im setting the data in service and from another component i'm getting that data|
Component- 1:
makeUser(row){
this.agentsService.setSelectedAgentData(row); // setting the data (row) in agentsService.
const mrf = this.modalService.open(MakeUserComponent);
}
Service:
declaring the varible in class.
public selectedData:any = {};
setter and getter methods are as below
setSelectedAgentData(selectedTableRowData){
this.selectedData = selectedTableRowData;
}
getSelectedAgentData(){
return this.selectedData;
}
Component - 2:
ngOnInit() {
this.userDetails = this.agentsService.getSelectedAgentData();
this.roles = this.agentsService.getRolesList();
}
Here the selectedData value is an empty object when I call the method this.agentsService.getSelectedAgentData() from component -2
Any help would be appreciated.

You can use Subject (rxjs library) for this purpose. So Subject can generate data on the one hand. And on the other hand, you can subscribe to changes in any place.
You service would look like this:
#Injectable()
export class YourService {
public selectedData: Subject<any>;
constructor() {
this.selectedData = new Subject();
}
generateSelectedAgentData(row: string) {
this.selectedData.next(row);
}
}
In your first Component:
makeUser(row){
this.agentsService.generateSelectedAgentData(row);
const mrf = this.modalService.open(MakeUserComponent);
}
In your second Component:
constructor(private ys: YourService){
this.ys.selectedData.subscribe(
data => {
console.log(data);
this.userDetails = data;
});
}

Related

Retrieve the data from one component to another

We are trying to use the NavigationExtras to pass data from one component to another (one page to another) like below
viewProjectDetails(e) {
const navigationExtras: NavigationExtras = {
state: {
ProjectInfo: e.data,
UserSelection: this.UserSelection
}
};
this.router.navigate(['dashboard/ProjectShipment'], navigationExtras);
}
I am trying to get the ProjectInfo and UserSelection array in to the another component
projDetail : any;
userSelection: any;
getPrjDetails() {
const navigation = this.activatedRoute.getCurrentNavigation();
const state = navigation.extras.state as {
}
Listen to the queryParams and catch the NavigationExtras
this.route.queryParams.subscribe(params => {
console.log(params["state"]);
});
constructor(private router: Router) {
console.log(this.router.getCurrentNavigation().extras.state.Projectinfo);
// should log e.data
}
You need to call getCurrentNavigation() method inside of the constructor, elsewhere the navigation has finished.

Shared service works only onInit - Angular

I want to pass an object between 2 components. I created the following shared service:
[PageService Component]
private messageSource = new BehaviorSubject([]);
currentMessage = this.messageSource.asObservable();
changeMessage(message) {
this.messageSource.next(message)
}
And I have implemented it in these 2 components:
[COMPONENT WHEN I GET ON CLICK SONO DATAS]
constructor(private pageService: PageService, private _sanitizer: DomSanitizer) {}
...
onClickMethod(){
self.pageService.getCustomers(self.filters).toPromise().then(response => {
self.searchResults = response;
});
self.pageService.changeMessage(self.searchResults);
}
and
[Component where I need to see above datas]
ngOnInit() {
let self = this;
self.pageService.currentMessage.subscribe(message => self.searchResults = message);
console.log(self.searchResults);
}
Now...if I put the "changeMessage" method in the first component in the method onInit or in the costructor and i try to pass some data like [1,2,3] (so not the response of another api rest) it seems to work...this doesn't work just when i put it inside onClick method and passing "self.searchResults" (the response)...anyone can help me?
Thanks
Go from this
self.pageService.getCustomers(self.filters).toPromise().then(response => {
self.searchResults = response;
});
self.pageService.changeMessage(self.searchResults);
To this
self.pageService.getCustomers(self.filters).toPromise().then(response => {
self.searchResults = response;
self.pageService.changeMessage(self.searchResults);
});
Because you make an HTTP call (I assume), you should wait for the call to end. In your code, it doesn't.

Angular2 - pass ASYNC data to child component

I have issue, with passing async data to child component. I trying to write dynamic form generator. Issue starts when I try to call json via Observable and pass it into child component.
service:
generateSearchFields2(): Observable<any> {
return this.http
.get(this.API + 'searchFields')
.map((res:Response) => {
res.json().data as any;
for (var i = 0; i < res.json().data.length; i++) {
var searchField = res.json().data[i];
switch (searchField.component) {
case "TextboxQuestion":
let TXQ: TextboxQuestion = new TextboxQuestion({
key: searchField.key,
label: searchField.label,
value: searchField.value,
required: searchField.required,
order: searchField.order
});
this.searchFieldModels.push(TXQ);
console.log("TXQ: ", TXQ, this.searchFieldModels);
break;
case "DropdownQuestion":
let DDQ: DropdownQuestion = new DropdownQuestion({
key: searchField.key,
label: searchField.label,
required: searchField.required,
options: searchField.options,
order: searchField.order
});
this.searchFieldModels.push(DDQ);
console.log("TXQ: ", DDQ, this.searchFieldModels);
break;
default:
alert("DEFAULT");
break;
}
}
return this.searchFieldModels.sort((a, b) => a.order - b.order);
})
.catch(this.handleError);
}
Component Parent:
generateSearchFields2() {
this.service.generateSearchFields2()
.subscribe(res => this.searchFields = res)
}
Iam passing variable via INPUT directive in parent template to child: [searchFields]="searchFields"
Issue is in child component, where searchField has undefined value. In this child I pass value to another service, to create formContros, but I got undefined there also. Data missing starts here, in child:
#Input() searchFields: SearchBase<any>[] = [];
ngOnInit() {
this.form = this.qcs.toFormGroup(this.searchFields);
console.log("ONINIT DYNAMIC FORM COMPONENT: ", this.searchFields);
}
Please for hint how I can pass async variable, to not loose data meantime
You can make #Input() searchFields a setter
private _searchFields: SearchBase<any>[] = [];
#Input() set searchFields(value SearchBase<any>[]) {
if(value != null) {
this.form = this.qcs.toFormGroup(this.searchFields);
console.log("ONINIT DYNAMIC FORM COMPONENT: ", this.searchFields);
}
}
get searchFields() : SearchBase<any>[] {
return this.searchFields;
}
You can also use ngOnChanges() which is called every time an input is updated, but a setter is usually more convenient except perhaps when the executed code depends on multiple inputs being set.
In the ngOnInit event the data which comes from the parent is not bound yet. So your searchFields is undefined yet. You can use it in NgAfterViewInit component lifecycle event.
#Input() searchFields: SearchBase<any>[] = [];
ngAfterViewInit() {
this.form = this.qcs.toFormGroup(this.searchFields);
console.log("ONINIT DYNAMIC FORM COMPONENT: ", this.searchFields);
}
For other cases you can see Angular2 Component Lifecycle events

How to wait until a variable is defined without using $scope $watch in angular?

Below is my code so far:
My Module
module App.SomeModule {
import ILabelSettingsViewModel = App.GeneralSettings.data.ILabelSettingsViewModel;
import IGeneralSettingsService = App.GeneralSettingsService.IGeneralSettingsService;
export enum LabelPageFormat {
A4,
Thermal
}
export interface IConsignmentDataService {
getAccountLabelFormat(): LabelPageFormat;
}
export class MyDataService implements IMyDataService {
accountLabelFormat: LabelPageFormat;
static $inject: string[] = ["generalSettingsService"];
constructor(private generalSettingsService: IGeneralSettingsService) {
this.determineAccountLabelFormat();
}
getAccountLabelFormat(): LabelPageFormat {
return this.accountLabelFormat;
}
private determineAccountLabelFormat() {
var that = this;
this.generalSettingsService.getLabelSettings().then((data: ILabelSettingsViewModel) => {
switch (data.name) {
case LabelPageFormat[LabelPageFormat.Thermal]:
that.accountLabelFormat = LabelPageFormat.Thermal;
break;
default:
that.accountLabelFormat = LabelPageFormat.A4;
break;
}
}, () => {
that.accountLabelFormat = LabelPageFormat.A4;
});
}
}
angular.module("app.common").service("myDataService", MyDataService);
}
and my controller
module App.Consignment.List {
"use strict";
import IConsignmentDataService = Consignment.IConsignmentDataService;
import ConsignmentListGridScope = Consignment.IConsignmentListGridScope;
class ConsignmentListController implements IConsignmentBulkActionProvider {
accountLabelFormat: LabelPageFormat;
static $inject = ["$scope", "myDataService"];
constructor(private $scope: ConsignmentListGridScope, private myDataService: IMyDataService) {
this.accountLabelFormat = this.consignmentDataService.getAccountLabelFormat();
}
}
angular.module("app.consignment").controller("consignmentListController", ConsignmentListController);
}
what I am trying to do is, get the accountLabelFormat from my data service and then use it to somewhere else. In data service, a method is used to get the format from database which is returned as a promise and then if success, I am setting the variable that will be returned when I call the getAccountLabelFormat() method from my controller. Now my problem is, as the service method is async, by the time I call the getAccountLabelFormat() method, the variable in accountLabelFormat service was not yet set, so that every time I got an undefined value in my controller. Any ideas about how can I solve this? Thanks in advance.
use $q.when. check out https://docs.angularjs.org/api/ng/service/$q
For example:
$q.when(this.accountLabelFormat)
so when you ask for that value it will return a promise then just chain it a then statement

Angular2 call observer next from child object

I'll try to explain this as best I can.
I have a service that contains an observable class that performs tasks to update itself. That observable class needs to be pushed out to the app using the observer located in the service. How can I call that observer from the child without creating some sort of dependency loop?
Here is a rough example:
class MyService {
subClass$: Observable<SubClass>;
_subClassObserver: Observer<SubClass>;
constructor(private _subClassStore: SubClass){
this.subClass$ = new Observable(observer => {
this._subClassObserver = observer
}).share();
}
pushData(){
this._subClassObserver.next(this._subClassStore)
}
}
class SubClass {
displayData: string;
displayData2: number;
constructor(){
socket.on('setData', function(obj){
this.displayData = obj.dd1;
this.displayData2 = obj.dd2;
//How to call pushData() in MyService from here to push data to app?
}
}
}
_subClassStore is updating through a stream coming in from socket.io. How do I let MyService know when the SubClass data changes so that it can push it using _subClassObserver.next(_subClassStore)?
EDIT:
I added more details to the example above to show how they are related and utilized.
SubClass is just a listener for a stream of data coming from socket.io and saving the information into the class. It starts listening when MyService is constructed.
The goal of MyService is to provide a bunch these sub classes that can be subscribed to across the app. Each one would allow access to a different data stream and the associated data, but all would be contained within a single service.
The question is how to call the pushData() function in the parent so that it keeps the stream updated for subscribers in the app.
Edit 2:
This might help. below is how it would be written as a service without the sub class. The only reason why I'm not doing this is because there are a substantial amount of these listeners being stored to Observables and abstracting them out into classes makes the information much easier to manage but pushing it to the app is what I can't figure out:
class MyService {
class1$: Observable<DataStream>;
_class1Observer: Observer<DataStream>;
_class1Store: DataStream;
constructor(){
this._class1store = {displayData: 'hello', displayData2: 0};
this.class1$ = new Observable(observer => {
this._class1Observer = observer
}).share();
socket.on('setData', function(obj){
this._class1Store.displayData = obj.dd1;
this._class1Store.displayData2 = obj.dd2;
this._class1Observer.next(this._class1Store)
}
}
interface DataStream = {
displayData: string;
displayData2: number;
}
Instead of function(obj) use ()=> otherwise this won't ponit to the MyService instance.
constructor(){
socket.on('setData', (obj) =>{
this.displayData = obj.dd1;
this.displayData2 = obj.dd2;
//How to call pushData() in MyService from here to push data to app?
}
}
I'm not sure but I think socket is prone to run outside Angulars zone.
Try also
constructor(zone:NgZone){
socket.on('setData', (obj) =>{
zone.run(() => {
this.displayData = obj.dd1;
this.displayData2 = obj.dd2;
//How to call pushData() in MyService from here to push data to app?
});
}
}
To be able to call a method in MyService from SubClass, SubClass needs a reference to MyService
class MyService {
subClass$: Observable<SubClass>;
_subClassObserver: Observer<SubClass>;
constructor(private _subClassStore: SubClass){
_subClassStore.myService = this;
this.subClass$ = new Observable(observer => {
this._subClassObserver = observer
}).share();
}
pushData(){
this._subClassObserver.next(this._subClassStore)
}
}
class SubClass {
displayData: string;
displayData2: number;
myService:MyService;
constructor(zone:NgZone){
socket.on('setData', (obj) =>{
zone.run(() => {
this.displayData = obj.dd1;
this.displayData2 = obj.dd2;
this.myService.pushData();
});
}
}
}

Categories