ionic4 Angular 7 query params subscribe is not triggering on every change when using ion-router-outlet - subscription

This is my code
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute, Params, Router } from '#angular/router';
#Component({
selector: 'app-landing',
templateUrl: './landing.page.html',
styleUrls: ['./landing.page.scss'],
})
export class LandingPage implements OnInit {
constructor(private activatedRoute: ActivatedRoute,
private router: Router) { }
ngOnInit() {
this.activatedRoute.queryParams.subscribe( (params: Params) => {
console.log(params);
});
}
navigate(query) {
this.router.navigate(['/landing'], {
queryParams: {mode: query},
});
}
}
My Html code is
<ion-content padding>
<h3>
<a (click)="navigate('signIn')" >Sign In</a>
</h3>
<h3>
<a (click)="navigate('signOut')">Sign Out</a>
</h3>
</ion-content>
Also I tried like
<a fill="clear" [routerLink]="['/landing']" [queryParams]="{'mode':'signIn'}">Tour of Heroes</a>
I'm trying to subscribe the query params. But it is not 'console' the changes when ever there is a change.
It works in 'router-outlet', but not in 'ion-router-outlet'
Can some one please tell me what I'm doing wrong here? Thank you.

Related

Error when using cdkDropListData in Angular gives me Can't bind to 'cdkDropListData' since it isn't a known property of 'div'

<div
cdkDropList
#girlList="cdkDropList"
[cdkDropListData]="girls"
[cdkDropListConnectedTo]="[convaList]"
class="example-list"
(cdkDropListDropped)="drop($event)"><div class="card color-challenging mb-2" *ngFor="let girls_data of girls" cdkDrag>
<div class="card-body p-2 justify-content-between align-items-center d-flex">
<span class="reading-grade font-weight-bold">{{girls_data.id}}</span>
<div class="student-grade flex flex-grow-1">
<p class="justify-content-between align-items-center d-flex">
<span class="student-name">{{girls_data.firstName}}{{girls_data.lastName}}</span>
<span>{{girls_data.gender}}</span>
</p>
<p class="justify-content-between align-items-center d-flex">
<span>{{girls_data.currentAcademicYear}}</span>
<span><i class="fa fa-ban" aria-hidden="true"></i> <i class="fa fa-paperclip" aria-hidden="true"></i></span>
</p>
</div>
<span class="behavior-grade text-right font-weight-bold">{{girls_data.inGrade}}</span>
</div>
</div>
When using [cdkDropListData] here gives me error on console that Can't bind to 'cdkDropListData' since it isn't a known property of 'div'.
I am new to angular so please avoid newbie behaviour
I already imported the CdkDragDrop in module.ts
This is the Component file.
import {Component, NgModule} from '#angular/core';
import {StudentModel} from '../model/studentRepository.model';
import {Student} from '../model/student.model';
import {CdkDragDrop, DragDropModule, moveItemInArray, transferArrayItem} from '#angular/cdk/drag-drop';
#Component({
selector: 'student-selector',
templateUrl: 'studentSelector.component.html',
styleUrls: ['./studentSelector.component.css']
})
export class StudentSelector {
boys = [];
girls = [];
constructor(private dataModel: StudentModel) {
this.boys = dataModel.getStudents();
this.girls = dataModel.getStudents();
}
get students(): Student[] {
return this.dataModel.getStudents();
}
conva = [];
drop(event : CdkDragDrop<string[]>){
transferArrayItem(event.previousContainer.data,
event.container.data,
event.previousIndex,
event.currentIndex);
}
}
Here is the module file.
import {NgModule} from '#angular/core';
import { StudentModel } from './studentRepository.model';
import { SimpleDataSource } from './datasource.model';
import {DragDropModule} from '#angular/cdk/drag-drop';
#NgModule({
providers: [StudentModel,SimpleDataSource],
imports : [DragDropModule]
})
export class ModelModule {
}
The imports should be like this:
import {NgModule} from '#angular/core';
import { StudentModel } from './studentRepository.model';
import { SimpleDataSource } from './datasource.model';
import {DragDropModule} from '#angular/cdk/drag-drop';
#NgModule({
providers: [StudentModel,SimpleDataSource],
imports : [DragDropModule]
})
export class ModelModule {
}
and (see notes in the code)
import {Component} from '#angular/core'; <= NgModule removed
import {StudentModel} from '../model/studentRepository.model';
import {Student} from '../model/student.model';
import {CdkDragDrop, moveItemInArray, transferArrayItem} from '#angular/cdk/drag-drop'; <= DragDropModule removed
#Component({
selector: 'student-selector',
templateUrl: 'studentSelector.component.html',
styleUrls: ['./studentSelector.component.css']
})
export class StudentSelector {
...
}
Generally:
xxxModule should only ever be imported on module level, not on component level.
Also, as I mentioned in the comments:
It looks like your StudentSelector is in a different module than your ModelModule (at least it is not part of the declarations you provided). A component can only be used in the module that declares it (declarations-list) OR that imports another module which in return declares the component and exports it (exports-list).
import this in your app module
import { DragDropModule} from '#angular/cdk/drag-drop';
and re run the app.
Most probably the issue can be not importing the correct module.
import { DragDropModule} from '#angular/cdk/drag-drop';
Still, if someone is facing this issue then it means you have not declared your component in any of your modules (Ex: App.module.ts)
Because this property requires module declaration.
(Ex: If someone opens a component using ComponentFactoryResolver, then it does not require to declare in app.module but to use '[cdkDropListData]', you need to declare it app.module)
This is not very technical solution but there are few things which I've faced.
1. Clear the cache before load the page (If you are not clearing it usually). Sometimes it misses to fetch the data to the variable.
2. Fix the run time bugs in the current page (may be in the another block but in the same page).
But I've faced the first issue. when I clear the cache it worked.

How to get access to `BsModalRef` in opened modal component?

I'm quite new to Angular 4.I have been working on Angular 1.5.x and now converting same application in Angular 4 with ngUpgrade hybrid approach.
I'm using ngx-bootstrap modal component in my hybrid application in order to replace existing modal service.
I found some problem in following guide ngx-bootstrap-modal with service.
Having problem with this statement If you passed a component to .show() you can get access to opened modal by injecting BsModalRef
I'm copying same example here,
export class ModalContentComponent {
public title: string;
public list: any[] = [];
constructor(public bsModalRef: BsModalRef) {} // How do you get bsModalRef here
}
I try running this example, but I never get bsModalRef in opened modal.
I also try passing bsModalRef through content, but it work with one modal and failed to work with nested modal.
Is there any other way to pass bsModalRef in ModalContentComponent ?
Find complete example here,
import { Component } from '#angular/core';
import { BsModalService } from 'ngx-bootstrap/modal';
import { BsModalRef } from 'ngx-bootstrap/modal/modal-options.class';
#Component({
selector: 'demo-modal-service-component',
templateUrl: './service-component.html'
})
export class DemoModalServiceFromComponent {
bsModalRef: BsModalRef;
constructor(private modalService: BsModalService) {}
public openModalWithComponent() {
let list = ['Open a modal with component', 'Pass your data', 'Do something else', '...'];
this.bsModalRef = this.modalService.show(ModalContentComponent);
this.bsModalRef.content.title = 'Modal with component';
this.bsModalRef.content.list = list;
setTimeout(() => {
list.push('PROFIT!!!');
}, 2000);
}
}
/* This is a component which we pass in modal*/
#Component({
selector: 'modal-content',
template: `
<div class="modal-header">
<h4 class="modal-title pull-left">{{title}}</h4>
<button type="button" class="close pull-right" aria-label="Close" (click)="bsModalRef.hide()">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<ul *ngIf="list.length">
<li *ngFor="let item of list">{{item}}</li>
</ul>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" (click)="bsModalRef.hide()">Close</button>
</div>
`
})
export class ModalContentComponent {
public title: string;
public list: any[] = [];
constructor(public bsModalRef: BsModalRef) {} // How do you get bsModalRef here
}
This issue is because of multiple references or circular references.
You should import all the ngx-bootstrap components, services directly from the ngx-bootstrap instead of going to the specific file.
import { BsModalRef,ModalModule ,BsModalService } from 'ngx-bootstrap';
LIVE DEMO
Solved by using
import { BsModalRef } from 'ngx-bootstrap';
Thanks to ngx-bootstap community on GitHub - Problem solution
Solved it by Import
import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service';

Change placement of NgbPopover if window is less than X

I am using Angular 4 and the Popover component from ng-bootstrap. It's working fine but I am trying to change its placement if window size is less than 600px. I couldn't find an option for that. My setup is similar to this:
import { Component, NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { JsonpModule } from '#angular/http';
import { NgbModule } from '#ng-bootstrap/ng-bootstrap';
import { NgbdPopoverTplcontent } from './popover-tplcontent';
#Component({
selector: 'my-app',
template: `
<div class="container-fluid">
<hr>
<p>
This is a demo plnkr forked from the <strong>ng-bootstrap</strong> project: Angular powered Bootstrap.
Visit https://ng-bootstrap.github.io for more widgets and demos.
</p>
<hr>
<ngbd-popover-tplcontent></ngbd-popover-tplcontent>
</div>
`
})
export class App {
}
#NgModule({
imports: [BrowserModule, FormsModule, ReactiveFormsModule, JsonpModule, NgbModule.forRoot()],
declarations: [App, NgbdPopoverTplcontent]
bootstrap: [App]
})
export class AppModule {}
HTML:
<p>
Popovers can contain any arbitrary HTML, Angular bindings and even directives!
Simply enclose desired content in a <code><ng-template></code> element.
</p>
<ng-template #popContent>Hello, <b>{{name}}</b>!</ng-template>
<button type="button" class="btn btn-secondary" [ngbPopover]="popContent" popoverTitle="Fancy content" placement="right">
I've got markup and bindings in my popover!
</button>
Plunker
How can I change the placement to top if window <= 600?
Try specifying the placement property like this:
[placement]="getPlacement()"
Then add this method to the component's class:
public getPlacement(): string {
return window.innerHeight <= 600 ? 'top' : 'right';
}

Angular 2: Can't bind to 'routerlink' since it isn't a known property of 'a'

I am new to angular 2 I am trying to create a sample application seeing one plural sight tutorial but I got above mentioned error when I try to create Routes.
I am not able to figure out why error coming.Could anyone please help.
app.component.ts
import { Component } from '#angular/core';
import { ProductService} from './products/product.service';
#Component({
selector: 'pm-app',
template: `
<div>
<nav class= 'navbar navbar-default'>
<div class ='container-fluid'>
<a class = 'navbar-brand'>{{pageTitle}}</a>
<ul class = 'nav navbar-nav'>
<li><a [routerlink]="['/welcome']">Home</a></li>
<li><a [routerlink]="['/products']">Product List</a></li>
</ul>
</div>
</nav>
<div class='container'>
<router-outlet></router-outlet>
</div>
</div>
`,
providers: [ ProductService ]
})
export class AppComponent {
pageTitle: string ="Acme Product Management";
}
app.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import {FormsModule} from '#angular/forms';
import {HttpModule} from '#angular/http';
import {RouterModule} from '#angular/router';
import {ProductListComponent} from './products/products-list.component';
import { AppComponent } from './app.component';
import {ProductFilterPipe} from './products/product-filter.pipe';
import {ProductDetailComponent} from './products/product-detail.component';
import {WelcomeComponent} from './home/welcome.component';
import {StarComponent} from './shared/star.component';
#NgModule({
imports: [ BrowserModule,FormsModule ,HttpModule,
RouterModule.forRoot([
{path : 'products',component:ProductListComponent},
{path:'Product/id',component :ProductDetailComponent},
{path:'welcome',component:WelcomeComponent},
{path:'',redirectTo:'welcome',pathMatch:'full'},
{path:'**',redirectTo:'welcome',pathMatch:'full'}
]),],
declarations:
[
AppComponent,ProductListComponent,ProductFilterPipe,StarComponent,
ProductDetailComponent,WelcomeComponent],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Regards,
Nagasree.
I got the mistake.
#NgModule ({
imports: [ BrowserModule,FormsModule ,HttpModule,
RouterModule.forRoot([
{path : 'products',component:ProductListComponent},
{path:'Product/id',component :ProductDetailComponent},
{path:'welcome',component:WelcomeComponent},
{path:'',redirectTo:'welcome',pathMatch:'full'},
{path:'**',redirectTo:'welcome',pathMatch:'full'}
**]),**
],
In the bold code I kept extra ',' last but one line in the mentioned code ]),.Once I remove it,started working.

Angular2 component - function not being recognised

I am trying to create a separate component to deal with the presentation of a news feed. It works fine when I have everything within app.component.ts, but when I separate the code into its own component (news-feed.component.ts) it initially displays fine but when a menu button is clicked (e.g.: <button (click)="getNews('the-telegraph')">telegraph</button>) it is failing to recognise the function 'getNews' and the following error is generated:'EXCEPTION: Error in ./AppComponent class AppComponent - inline template:4:12 caused by: self.context.getNews is not a function'.
Please note - it is successfully running the getNews() function within the NewsFeedComponent when the site first loads.
Here is app.component.ts:
import {Component} from '#angular/core';
import {NewsService} from './news.service';
import {Observable} from 'rxjs/Rx';
import { NewsFeedComponent } from './news-feed.component';
#Component({
selector: 'news-app',
template:`
<h1>News Feed</h1>
<nav>
<button (click)="getNews('bbc-news')">bbc</button>
<button (click)="getNews('the-telegraph')">telegraph</button>
<button (click)="getNews('the-guardian-uk')">guardian</button>
<button (click)="getNews('independent')">independent</button>
<button (click)="getNews('financial-times')">financial times</button>
<button (click)="getNews('the-economist')">the economist</button>
<button (click)="getNews('sky-news')">sky news</button>
<button (click)="getNews('the-new-york-times')">the new york times</button>
</nav>
<news-feed></news-feed>
`,
styleUrls: ['app/app.component.css']
})
export class AppComponent {
}
Here is news-feed.component.ts:
import {Component} from '#angular/core';
import {NewsService} from './news.service';
import {Observable} from 'rxjs/Rx'
#Component({
selector: 'news-feed',
template: `
<ul>
<li *ngFor="let article of news">
hello2
<h2>{{article.title}}</h2>
<p>{{article.publishedAt}}</p>
<img src="{{article.urlToImage}}" style="width: 200px;">
<p>{{article.description}}</p>
</li>
</ul>
`
})
export class NewsFeedComponent {
// public news;
constructor(private _newsService: NewsService) { }
ngOnInit() {
this.getNews('bbc-news');
}
getNews(source) {
this._newsService.getNews(source).subscribe(
// the first argument is a function which runs on success
data => {
this.news = data['articles']
},
error => {
//console.error("Error saving food!");
return Observable.throw(error);
}
);
}
}
Here is app.module.ts:
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { HttpModule } from '#angular/http';
import {FormsModule} from '#angular/forms';
import {NewsService} from './news.service'
import { AppComponent } from './app.component';
import { NewsFeedComponent } from './news-feed.component';
#NgModule({
imports: [BrowserModule,HttpModule,FormsModule],
declarations: [
AppComponent,
NewsFeedComponent
],
providers: [NewsService],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
bootstrap: [AppComponent]
})
export class AppModule { }
Apologies for cutting and pasting in all this code. I have tried to get this working on Plunker and have failed due to being very stupid. Any help would be much appreciated.
As commented at the question by #echonax and #devqon, you are calling getNews from AppComponent which is defined in your child component NewsFeedComponent. If this is the problem, try to move the function getNews to the AppComponent.
And, If you just want to call a child component's function, you can do it this way.
<nav>
<button (click)="newsFeed.getNews('bbc-news')">bbc</button>
// all the same
</nav>
<news-feed #newsFeed></news-feed>
You shouldn't be calling getNews function from your AppComponent html(as getNews isn't available in its context). Rather what you should be doing is, on click of button you should set some variable as like feedType = 'bbc-news' and pass it as input binding to your news-feed.
There it will receive type of feed dynamically using #Input binding and you can call the getNews method with selected appropriate feedType
<h1>News Feed</h1>
<nav>
<button (click)="feedType = 'bbc-news'">bbc</button>
<button (click)="feedType = 'the-telegraph'">telegraph</button>
<button (click)="feedType = 'the-guardian-uk'">guardian</button>
<button (click)="feedType = 'independent'">independent</button>
<button (click)="feedType = 'financial-times'">financial times</button>
<button (click)="feedType = 'the-economist'">the economist</button>
<button (click)="feedType = 'sky-news'">sky news</button>
<button (click)="feedType = 'the-new-york-times'">the new york times</button>
</nav>
<news-feed [feedType]="feedType"></news-feed>
Then add Input property binding in news-feed component
#Input() feedType;
constructor(private _newsService: NewsService) { }
//call getNews with selected `feedType`
ngOnInit() {
this.getNews(this.feedType);
}

Resources