I have a angular 5 app with routing in which my app.routes.module.ts file handles the route for criminal
{ path: 'criminal', component: CriminalComponent, pathMatch: 'full'},
However, in navigating to here, I'm upgrading an old site to angular and I'm for now using the generated URL links example:
<td href="/criminal/?UserID=67694&AppID=4&AppGroupID=13&AM&LoginKey=202088840" >CR Programmers</a></td>
I wasn't sure if I should be tampering with the route file for all these querystring parameters so for the MENU generation I was placing it in there.
ngOnInit(): void { .... }
So inside OnInit I know I need to parse out the querystring
Then I need to make a service call passing in all the params
When I had them separate, it seems that conditional if on if there WAS a menu was NOT processed in time and no menu service call would happen.
Is there a way to have my service call subscribe to the query params section?
this.activatedRoute.queryParamMap
.map((params: Params) => params.params)
.subscribe((params) => {
if (params && params['UserID']) {
let UserID = params['UserID'];
let AppID = params['AppID'];
console.log('UserID', UserID);
console.log('AppID', AppID);
this.hasMenu = 1;
console.log('hasmenu', this.hasMenu)
this.arsSevice.getMenu() //will pass params
.subscribe(
result => {
this.menuA = result["data"].Menu1Items
this.menuB = result["data"].Menu2Items
this.menuC = result["data"].Menu3Items
this.menuD = result["data"].Menu4Items
this.menuE = result["data"].Menu5Items
},
error => {
console.log('menu error', error);
})
}
});
Basically above code has the getMenu() call ( which is not currently passing params)
I would LIKE to not have it NESTED inside
this part i would prefer to do like this
if (this.hasMenu == 1) {
this.arsSevice.getMenu()
.subscribe(
result => {
this.menuA = result["data"].Menu1Items
this.menuB = result["data"].Menu2Items
this.menuC = result["data"].Menu3Items
this.menuD = result["data"].Menu4Items
this.menuE = result["data"].Menu5Items
},
error => {
console.log('menu error', error);
})
}
You can use filter to do conditional checking and flatMap/map to chain them up
this.activatedRoute.queryParamMap
.map((params: Params) => params.params)
.filter((params) => params && params['UserID'])
.flatMap(params=>{
..... your other operation
return this.arsSevice.getMenu()
}).map( result => {
this.menuA = result["data"].Menu1Items
this.menuB = result["data"].Menu2Items
this.menuC = result["data"].Menu3Items
this.menuD = result["data"].Menu4Items
this.menuE = result["data"].Menu5Items
}).subscribe()
Related
This can be a simple question but since I'm in a learning curve of vuejs I'm struggling to achieve following task.
I have this method inside one of my vue component.
async loadSuggestedUsers() {
if (!this.suggestionUrl) return false
else this.isSearching = true;
this.cancelPreviousRequest();
await axios.get(`/${Helper.getLocale()}/dashboard/${this.suggestionUrl}`, {
params: {
page: this.suggestedUsersData.page,
per_page: this.suggestedUsersData.perPage,
search_text: this.searchText,
nationality: this.selectedNationalities
},
cancelToken: this.requestToken.token
}).then(({data}) => {
collect(data.data).each((user) => {
if (!this.suggestedUsers.some(obj => obj.id === user.id)) {
this.suggestedUsers.push(user)
} else if (
user.project_specific_job_title_id &&
!this.suggestedUsers.some(obj => obj.project_specific_job_title_id === user.project_specific_job_title_id)
) {
this.suggestedUsers.push(user)
}
})
this.suggestedUsersData.perPage = data.per_page
this.suggestedUsersData.total = data.total
this.isSearching = false
}).catch(error => {
if (error instanceof axios.Cancel) return false;
});
},
but now, Instead of directly calling this method from the component I'm trying to access this by using store .
Under my store, I have a js file called, TestStore.JS
My questions are,
How can I re-create above method in my TestStore.JS and how call that recreated method in my component...
One solution is to create a state for this function in your store and pass its reference to it in the created lifecycle of the component.
I have a function that when the component is loaded, it returns specific data of a certain parameter (ex: /app/items) and displays them in an information balloon, but if I access a child route (ex: /app/items/ create) or (ex: /app/items/1/view) I need to do a validation to see if there is informational data in this route to display, but if not, I need to display the information from the previous parameter (ex: /app/items) . I managed to create this function below that fulfills this, but with a request inside another, which I believe is not the most appropriate. So I'm trying to refactor so that only one request is made validating these parameters. It should also be considered that if the route has numbers, it needs to be filtered and returned an array with just the strings before doing the join('/'), as you can see there in the constructor. I'm new to the area, so I'm trying to find some background to refactor this function.
public information: InformationList | any
public isLoading:boolean = true
error: any;
showError: boolean = false
public currentPageUrl = null;
public output = null
other: any;
constructor(
public screenInfoService: ScreenInfoService,
public loaderService: LoaderService,
public router: Router
) {
this.currentPageUrl = this.router.url.split("/").filter((item: any) => {
return isNaN(item)
})
}
load() {
this.output = this.currentPageUrl.join("/");
let params = new HttpParams();
params = params.set('orderBy', 'id');
params = params.set('search', `path:${this.output}`);
params = params.set('searchFields', `path:ilike`);
params = params.set('searchJoin', 'and');
this.screenInfoService.getAll(params).subscribe(
success => {
if (success.length === 0) {
let output2 = null
output2 = this.currentPageUrl.slice(0,2).join("/");
params = params.set('orderBy', 'id');
params = params.set('search', `path:${output2}`);
params = params.set('searchFields', `path:ilike`);
params = params.set('searchJoin', 'and');
this.screenInfoService.getAll(params).subscribe(
success => {
this.information = success
}, error => {
this.error = 'MSG.T224';
this.showError = true;
}
)
} else {
this.information = success
}
}, error => {
this.error = 'MSG.T224';
this.showError = true;
});
}
ngOnInit(): void {
this.load()
}
I have 2 components which is Component A and Component B , Component A is calling component B via selector , the app-team-users is the selector , it is calling data from API and then populating it on the table which is working fine.
In Component A I called the component B selector , in Component A I have a feature where I create a user or save a user .
How do we refresh or call the app-team-users selector so that if I save a user from Component A then the table on Component B will refresh which is the app-team-users will refresh ? cause they are seperate component. Maybe anyone has idea or enlightenment ? Thank you very much. Good day.
#Component A save user code
saveUser() {
if(this.createUserForm.valid) {
this.accountService.create(this.createUserForm.value).pipe(
finalize(() => {
this.isInProgress = false;
})
).subscribe({next: (res) => { this.notificationService.showSuccess('User has been created successfully.');
//if user is created refresh the selector
},
error: (err) => {this.notificationService.showError('Something went wrong, Try again later.');
this.isInProgress = false;
},
complete: () => {
this.isInProgress = false;
},
});
}
}
app-team-users table
#Code for calling the selector Component A
<form [formGroup]="modelForm" >
<app-team-users [selectedNewUser] = "newUsers" [selectedTransactionTeam]="modelForm.value.teams"
[selectedTransactionUser]="modelForm.value.users" (transactionUserEvent)="transactionUserEvent($event)"
(transactionTeamEvent)="transactionTeamEvent($event)">
</app-team-users>
</form>
#app-team-users code
ngOnInit(): void {
this.transactionUserTable.dataSource = new MatMultiSortTableDataSource(this.sort, this.CLIENT_SIDE);
this.transactionUserTable.nextObservable.subscribe(() => { this._transactionUserPageEvent(); });
this.transactionUserTable.sortObservable.subscribe(() => { this._transactionUserPageEvent(); });
this.transactionUserTable.previousObservable.subscribe(() => { this._transactionUserPageEvent(); });
this.transactionUserTable.sizeObservable.subscribe(() => { this._transactionUserPageEvent(); });
}
private _transactionUserPageEvent() {
this.isTransactionUserLoading = true;
this.transactionUserTable.data = [];
this._userProfileService.getUserProfileTableDropdown(
this.accountId,
this.transactionUserTable.pageIndex + 1,
this.transactionUserTable.pageSize,
this.searchTransactionUserInput.nativeElement.value,
this.transactionUserTable.sortParams,
this.transactionUserTable.sortDirs
)
.pipe(
finalize(() => this.isTransactionUserLoading = false)
)
.subscribe({
error: err => this._notificationService.showError(err),
next: res => {
this.transactionUserTable.totalElements = res.totalItemCount;
this.transactionUserTable.data = res.items as UserProfileDropdownDto[];
this.totalData = res.totalItemCount;
this.currentDisplayedData = res.lastItemOnPage;
},
complete: noop
});
}
You can do it via Observables.
Emit a value to an observable when a user is created in the first place. You can either pass the entire user value inside the observable and use that data to populate the second component from the front side itself. Or you can just pass a value, just to know in the second component that something has been created in the first one, then you call the same api to populate in the second component.
I am completely a newbie to Angular. Some how struggled to get the initial code working now I am stuck here.
Use case : Show loading bar. Fetch merchant list to an observable. Stop loading bar.
Problem:
fetchUsers($event) {
let searchTerm = $event.term;
if (searchTerm.length > 3) {
this.isLoading=true;
this.people$ = null;
this.userService.getMerchantsBySearch(searchTerm);
--> this.isLoading=false;
}
}
this.isLoading becomes false even before getting the response from getMerchantsBySearch call. I know I will need to perform this step in callback but I am not sure how to.
I want to do something like this but I a missing something. What is the correct way to do it.
fetchUsers($event) {
let searchTerm = $event.term;
if (searchTerm.length > 3) {
this.isLoading=true;
this.people$ = null;
this.userService.getMerchantsBySearch(searchTerm).subscribe(
res={
---> this.people$ =res;
---> this.isLoading=false;
}
);
}
}
dashboard.component.ts
people$: Observable<IMerchant[]>;
fetchUsers($event) {
let searchTerm = $event.term;
if (searchTerm.length > 3) {
this.isLoading=true;
this.people$ = null;
this.userService.getMerchantsBySearch(searchTerm);
this.isLoading=false;
}
}
user.service.ts
getMerchantProfile(id){
var options = this.getOptions();
return this.http.get<IMerchant[]>(environment.APIBaseURL+"/getMerchantProfile/"+id,options);
}
merchant.model.ts
export interface IMerchant{
email:String,
mobile : String,
password: String,
businessName : String,
otp:Number,
info:string,
url:String
}
i prefer using the teardown method .add(). it doesn't pollute your pipe chain of data manipulation and is also executed after an error is handled:
this.userService.getMerchantsBySearch(searchTerm)
.pipe(
// manipulate data here
)
.subscribe(
res => {
// handle final data
},
error => {
// handle error
}
).add(() => {
// teardown here (e.g. this.isLoading=false;)
});
By the way: if this.people$ is an observable, you can not assign it inside the subscribe callback. you'll need to assign it to the response of the userService method you are using. Be careful not to call subscribe on the stream since it will return you a subscription instead of an observable:
this.people$ = this.userService.getMerchantsBySearch(searchTerm).pipe(...)
You can actually pipe it and add a finalize
this.userService.getMerchantsBySearch(searchTerm)
.pipe(finalize(() => this.isLoading=false))
.subscribe(
res => {
this.people$ =res;
});
I am calling two API to return objects of data. Than run through for each of them and search if it has a value.
I want to check if one of these obj has a vas value matches.
getdata(slug){
this._apiService.getPages().subscribe(data =>{
this.pageobj = data
console.log('this page obj',this.pageobj)
})
this._apiService.getPosts().subscribe(data =>{
this.postsobj = data;
console.log('this post obj',this.postsobj)
})
}
this.pageobj is an object
this.postsobj
in both responses they had a property 'slug'.
I would like to check if in this.postsobj or this.pageobj has an object that contains 'slug' == 'hello-word', if so to return me object and store in var this.content
UPDATE
export class PageSingleComponent implements OnInit {
page: Page;
pageobj:any;
postsobj:any;
pageobjCheck:any
postsobjCheck:any
pageSlug:any;
content =new Array<any>();
constructor( private _apiService: apiService, private route: ActivatedRoute ) { }
getdata(slug){
this._apiService.getPages().subscribe(data =>{
this.pageobj = data
this.content.push(_.filter(this.pageobj, { 'slug':' hello-world' }));
})
this._apiService.getPosts().subscribe(data =>{
this.postsobj = data;
this.content.push(_.filter(this.postsobj, { 'slug':' hello-world' }));
})
}
ngOnInit() {
this.route.params.forEach((params: Params) => {
// Get slug from the rout
let slug = params['pageslug'];
console.log('slug is catcheds', slug)
this.pageSlug = params['pageslug'];
this.getdata(slug)
// Run functions
//
});
}
}
I think you want to use Filter function.
In your callback function passed to map function you want to check whether your response object form array has slug property which is equal to 'hello world'. Your code will like like this:
var content = response.filter(obj => obj && obj.slug === 'hello-world');
I prefer using lodash as below,
this.content =new Array<any>();
this.content.push(_.filter(this.pageobj, { 'slug':' hello-world' });
this.content.push(_.filter(this.postsobj, { 'slug':' hello-world' });
Alternatively you can handle it in the service using takeWhile operator
getPages(){
return this.http.get(...)
.takeWhile(data=>{
if(data.slug ==== 'hello-world'){
return data;
}
})
}