I am doing project in angular6. I have put "openModal" button. After clicking on that button popup need to be show. But I am not getting popup. But data which suppose to display on popup will getting display on same page. I am not getting where I have done mistake. Please anyone help me to find, where I have done mistake.
Here I have attached screenshot of output which I am getting.
https://imgur.com/Qjiy7jy
Here is my code
app.component.html
<button (click)="openModal()">Open Dialog</button>
app.component.ts
import { Component } from '#angular/core';
import { MatDialog, MatDialogConfig } from '#angular/material';
import { MyDialogComponent } from './my-dialog/my-dialog.component';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
constructor(public dialog: MatDialog) { }
openModal() {
console.log("calling");
const dialogConfig = new MatDialogConfig();
dialogConfig.disableClose = true;
dialogConfig.autoFocus = true;
dialogConfig.data = {
id: 1,
title: 'Angular For Beginners'
};
const dialogRef = this.dialog.open(MyDialogComponent, dialogConfig);
dialogRef.afterClosed().subscribe(result => {
alert("response: " + result)
});
}
}
my-dialog.component.html
<p>
my-dialog works!
</p>
my-dialog.component.ts
import { Component, Inject } from '#angular/core';
import { MAT_DIALOG_DATA } from '#angular/material';
import {MatSelectModule} from '#angular/material/select';
import {FormControl, Validators} from '#angular/forms';
import {MatInputModule} from '#angular/material'
export interface Staff {
name: string;
}
#Component({
selector: 'app-my-dialog',
templateUrl: './my-dialog.component.html',
styleUrls: ['./my-dialog.component.css']
})
export class MyDialogComponent {
modalTitle: string;
constructor(#Inject(MAT_DIALOG_DATA) public data: any) {
this.modalTitle = data.title;
console.log(data)
}
staffControl = new FormControl('', [Validators.required]);
selectFormControl = new FormControl('', Validators.required);
}
add in your module
entrycomponent:[yourdailogComponent]
and import css in your style.css
#import '~#angular/material/prebuilt-themes/indigo-pink.css';
openHashTagDialog() {
const dialogRef = this.dialog.open(AddHashTagdialogComponent, {
data: '',
width: '400px'
});
dialogRef.afterClosed().subscribe(result => {
this.fetchHashTagsList();
});
}
Related
Can someone help me out how to pass on a value for the constructor of a component which is created dynamically?
This is how the component FilterComponent is created:
import { Component, ComponentFactory, ComponentFactoryResolver, ComponentRef, OnInit, ViewChild, ViewContainerRef } from '#angular/core';
import { FilterComponent } from '../filter/filter.component';
export enum FilterType {
DateRangeFilter, SensorSelectFilter
}
#Component({
selector: 'app-filter-collection',
templateUrl: './filter-collection.component.html',
styleUrls: ['./filter-collection.component.css']
})
export class FilterCollectionComponent implements OnInit {
filters: Array<ComponentRef<FilterComponent>> = [];
#ViewChild("messagecontainer", { read: ViewContainerRef }) entry!: ViewContainerRef;
constructor(private resolver: ComponentFactoryResolver) { }
onAddDateRangeFilter() {
const factory: ComponentFactory<FilterComponent> = this.resolver.resolveComponentFactory(FilterComponent);
const filter = this.entry.createComponent<FilterComponent>(factory);
this.filters.push(filter);
}
ngOnInit(): void {
}
}
and this is the component:
#Component({
selector: 'app-filter',
templateUrl: './filter.component.html',
styleUrls: ['./filter.component.css']
})
export class FilterComponent {
constructor(private type : FilterType) {
}
ngOnInit(): void {
}
}
I am not sure if there is a way to access the constructor. But there is a way to get the actual instance of your dynamically generated component
import { Component, ComponentFactory, ComponentFactoryResolver, ComponentRef, OnInit, ViewChild, ViewContainerRef } from '#angular/core';
import { FilterComponent } from '../filter/filter.component';
export enum FilterType {
DateRangeFilter, SensorSelectFilter
}
#Component({
selector: 'app-filter-collection',
templateUrl: './filter-collection.component.html',
styleUrls: ['./filter-collection.component.css']
})
export class FilterCollectionComponent implements OnInit {
filters: Array<ComponentRef<FilterComponent>> = [];
#ViewChild("messagecontainer", { read: ViewContainerRef }) entry!: ViewContainerRef;
constructor(private resolver: ComponentFactoryResolver) { }
onAddDateRangeFilter() {
const factory: ComponentFactory<FilterComponent> = this.resolver.resolveComponentFactory(FilterComponent);
const filter:ComponentRef<FilterComponent> = this.entry.createComponent<FilterComponent>(factory);
this.filters.push(filter);
// you can use the componentRef.instance to reference any variables inside your dynamically generated component
filter.instance.type = FilterType.DateRangeFilter
}
ngOnInit(): void {
}
}
I am new to angular so please help me. I have an api returning an array of objects containing name, place id.
I need to display this in different cards on my html page, the cards being a widget.
in the parent component under the ngOnInit() section how do I access this json data and loop through the array in order to display it on my page as different cards?
Thank you in advance.
import { Component, OnInit } from '#angular/core';
import {HttpClient} from '#angular/common/http';
import { Observable } from 'rxjs/observable';
#Component({
selector: 'app-home-page',
templateUrl: './home-page.component.html',
styleUrls: ['./home-page.component.css']
})
export class HomePageComponent implements OnInit {
showSplash = true
//public events: any = [];
events = [];
constructor(private http : HttpClient) { }
ngOnInit() {
this.showSplash = true
this.http.get("/events").subscribe(data => {
console.log("EVENTS ARE: ", data);
this.events = data;
console.log(this.events)
})
}
ngAfterViewInit(){
setTimeout(() => {
this.showSplash = false
}, 3000);
}
}
This will get you the events you want.
import { Component, OnInit, OnDestroy } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Subscription } from 'rxjs';
#Component({
selector: 'app-home-page',
templateUrl: './home-page.component.html',
styleUrls: ['./home-page.component.css']
})
export class HomePageComponent implements OnInit, OnDestroy {
showSplash = true
events = [];
subscription: Subscription;
constructor(private http: HttpClient) {}
ngOnInit() {
this.subscription = this.http.get("/events").subscribe(data => {
this.events = data;
this.showSplash = false;
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
You will have to implement a Child Component(EventComponent probably with the selector app-event) that will accept an event object as an #Input property. Then in your HomePageComponent Template, you can loop through the events like this:
<div *ngFor="let event of events">
<app-event [event]="event"></app-event>
</div>
Alternatively:
You can use the async pipe in your HomePageComponent's Template to avoid manually unsubscribing from the Observable Subscription. Your HomePageComponent Class code will change to:
import { Component, OnInit } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'app-home-page',
templateUrl: './home-page.component.html',
styleUrls: ['./home-page.component.css']
})
export class HomePageComponent implements OnInit {
events$;
constructor(private http: HttpClient) {}
ngOnInit() {
this.events$ = this.http.get("/events");
}
}
And then in HomePageComponent's Template:
<div *ngFor="let event of events$ | async">
<app-event [event]="event"></app-event>
</div>
Here's how your EventComponent would look like in this case:
import { Component, Input, OnChanges } from '#angular/core';
#Component({
selector: 'app-event',
templateUrl: './event.component.html',
styleUrls: ['./event.component.css']
})
export class EventComponent implements OnChanges{
#Input() event;
ngOnChanges() {
this.events$ = this.http.get("/events");
}
}
I have a component.ts file which is making a http call & retrieving json data as response. I need to use this response in another component.ts file. Can anyone tell me how to process this?
first component.ts:
#Component({
selector: 'app-cat',
templateUrl: './first.component.html',
styleUrls: ['./first.component.css']
})
export class firstComponent extends Lifecycle {
this.http.get('/name',{responseType:"json"}).subscribe(
response => {
console.log("data :"+response);
console.log("data stringify:"+JSON.stringify(response));
});
}
I need to use the json content which is in the response in my second component file. Can anybody tell me how to proceed this in angular6?
****Create separate service for making calls and in that service create a method as such
public getData(): Observable<> {
return this.http.get('/name',{responseType:"json"}).subscribe(
response => {
console.log("data :"+response);
console.log("data stringify:"+JSON.stringify(response));
});
}
****And in your component declare service in constructor //don't forget to import it
public jsonData:any;
constructor(private Service: Service ) {
}
getData() {
this.Service.getData().subscribe(data => {
console.log("Data is ",data);
this.jsonData = data;
},
error => console.log(error)
);
}
Finally,you can use jsonData to work with your data.
Parent to Child: Sharing Data via Input
parent.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-parent',
template: `
<app-child [childMessage]="parentMessage"></app-child>
`,
styleUrls: ['./parent.component.css']
})
export class ParentComponent{
parentMessage = "message from parent"
constructor() { }
}
child.component.ts
import { Component, Input } from '#angular/core';
#Component({
selector: 'app-child',
template: `
Say {{ message }}
`,
styleUrls: ['./child.component.css']
})
export class ChildComponent {
#Input() childMessage: string;
constructor() { }
}
Sharing Data via Output() and EventEmitter
parent.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-parent',
template: `
Message: {{message}}
<app-child (messageEvent)="receiveMessage($event)"></app-child>
`,
styleUrls: ['./parent.component.css']
})
export class ParentComponent {
constructor() { }
message:string;
receiveMessage($event) {
this.message = $event
}
}
child.component.ts
import { Component, Output, EventEmitter } from '#angular/core';
#Component({
selector: 'app-child',
template: `
<button (click)="sendMessage()">Send Message</button>
`,
styleUrls: ['./child.component.css']
})
export class ChildComponent {
message: string = "Hola Mundo!"
#Output() messageEvent = new EventEmitter<string>();
constructor() { }
sendMessage() {
this.messageEvent.emit(this.message)
}
}
please visit https://angularfirebase.com/lessons/sharing-data-between-angular-components-four-methods/ for other methods.
Solution 1 using a common injectible service
Shared.service.ts
#Injectible()
class SharedService {
function getData():any{
return this.http.get('/name',{responseType:"json"}).subscribe(
response => {
console.log("data :"+response);
console.log("data stringify:"+JSON.stringify(response));
});
}
}
Solution 2 using a parent child component
Second.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-first-component',
template: `<p>{{data}}</p>`
})
export class SecondComponent{
data:any={};
ngOnInit(){this.getData();}
function getData():any{
this.http.get('/name',{responseType:"json"}).subscribe(
response => {
console.log("data :"+response);
console.log("data stringify:"+JSON.stringify(response));
this.data=data
});
}
}
parent.component.ts
import { Component } from '#angular/core';
import { SecondComponent } from './second.component';
#Component({
selector: 'app-first-component',
template: `
<h3>Get data (via local variable)</h3>
<button (click)="second.getData()">GetData</button>
<app-first-component #second></app-first-component>
`
})
export class FirstComponent{ }
Use Input & Output Decorators
Basic concept ---> DEMO
app.component.html:
<app-component1 (elm)="catch1Data($event)">
</app-component1>
<app-component2 [elm]="datatocomp2" *ngIf="datatocomp2"></app-component2>
parent component : {{datatocomp2 | json}}
app.component.ts:
datatocomp2: any;
catch1Data(data) {
console.log(data)
this.datatocomp2 = data;
}
component1.ts:
#Output () elm : EventEmitter<any> = new EventEmitter<any>();
objectData: any;
constructor() { }
ngOnInit() {
let objectData = {
comp: 'component 1',
data: 'anything'
}
this.objectData = objectData;
this.elm.emit(objectData)
}
component2.ts:
#Input() elm: any;
constructor() { }
ngOnInit() {
console.log(this.elm);
}
You can create store service for your 'global' data:
store.service.ts
import { Injectable } from '#angular/core';
#Injectable()
export class StoreService {
protected store: Map<string, any> = new Map();
constructor() { }
public get(key: string): any {
return this.store.get(key);
}
public set(key: string, value: any) {
this.store.set(key, value);
}
}
And then in yours component (lets call it X) you save data to store:
x.component.ts
import { Component, OnInit } from '#angular/core';
import { HttpClinet } from '#angular/common/http';
import { StoreService } from './store-service.service.ts';
#Component({
selector: 'app-x',
templateUrl: './x.component.html',
styleUrls: ['./x.component.css']
})
export class XComponent implements OnInit {
constructor(
private store: StoreService,
private http: HttpClient,
) { }
ngOnInit() {
}
getResource() {
this.http.get('/name',{responseType:"json"}).subscribe(
response => {
this.store.set('response', response);
console.log("data :"+response);
console.log("data stringify:"+JSON.stringify(response));
});
}
And then in yours other component (lets call it Y) you get your data:
y.component.ts
import { Component, OnInit } from '#angular/core';
import { StoreService } from './store-service.service.ts';
#Component({
selector: 'app-y',
templateUrl: './y.component.html',
styleUrls: ['./y.component.css']
})
export class YComponent implements OnInit {
constructor(
private store: StoreService
) { }
ngOnInit() {
}
getSavedResponse() {
// ask store for the resource
return this.store.get('response');
});
}
This is just simple example, if you know the structure of your response got by http call it would be good idea to make model of it.
Using the store any component can get or set store data.
If you need something more complex look for: #ngrx/store
Cases when you would not need store service:
If you do that http call in parent component then you can use child inputs to pass the data.
If you make that call in child component then use #Output and EventEmitter, to pass up the data (just one level, you can not do this to pass to grandparent)
Regards.
I am having some trouble figuring out where I went wrong and would really appreciate some help with this.
I have a component: AudioComponent, which captures an html5 tag as a #ViewChild, then registers itself with a service: AudioService.
Here is the AudioComponent:
/* audio.component.ts */
import { Component, OnInit, Input, ViewChild } from '#angular/core';
import { IAudioOptions } from './audio-options';
export const defaultOptions: IAudioOptions = {
controls: true,
autoplay: false,
loop: false,
volume: 1.0,
startPosition: 0.0,
preload: "metadata",
muted: false
};
#Component({
selector: 'ng-audio',
templateUrl: './audio.component.html',
styleUrls: ['./audio.component.css']
})
export class AudioComponent implements OnInit {
#Input() src: any;
#Input() options: any = defaultOptions;
#Input() register: any;
#ViewChild('audio') player: any;
constructor() { }
ngOnInit() {
if (this.register) {
console.log("registering");
console.log(this.register(this));
}
}
play() {
this.player.nativeElement.play();
}
}
And the AudioService:
/* audio.service.ts */
import { Injectable } from '#angular/core';
import { AudioComponent } from './audio/audio.component';
#Injectable()
export class AudioService {
private players: AudioComponent[];
constructor() { }
register(player: AudioComponent) {
console.log("player registered");
if (this.players) {
this.players.push(player);
}
else {
console.log("initializing service");
this.players = [];
this.players.push(player);
}
return this.players;
}
getPlayers(): string[] {
var out: string[];
for (let i = 0; i < this.players.length; i++) {
out.push(this.players[i].src);
}
return out;
}
}
I'm instantiating two of the ng-audio components in my app.component.html file:
<!-- register refers to the AudioService.register function -->
<ng-audio [src]="src" [register]="register"></ng-audio>
<ng-audio [src]="src2" [register]="register"></ng-audio>
And the audio players themselves appear when I load the page.
What's puzzling is that I get the following logged to the console:
- registering
- player registered
- initializing service
- [AudioComponent]
- registering
- player registered
- initializing service // <- this should only happen the first time!
- [AudioComponent] // <- and this should now contain two elements!
For some reason, the players: AudioComponent[] property of the AudioService does not persist. So each time register() is called, it's like I'm calling it on a completely new AudioService instance!
Again, any help will be greatly appreciated. I'll be posting updates if I can figure this out.
EDIT: I've included my app.module.ts and app.component.ts files in case there's something I missed setting up the service as a provider.
AppModule:
/* app.module.ts */
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppComponent } from './app.component';
import { AudioComponent } from './audio/audio.component';
import { AudioService } from './audio.service';
#NgModule({
declarations: [
AppComponent,
AudioComponent
],
imports: [
BrowserModule
],
exports: [AudioComponent],
providers: [AudioService],
bootstrap: [AppComponent]
})
export class AppModule { }
And AppComponent:
/* app.component.ts */
import { Component } from '#angular/core';
import { AudioComponent } from './audio/audio.component';
import { AudioService } from './audio.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
src = 'http://url.to/file.mp3';
src2 = 'http://url.to/another-file.mp3';
interval: any;
player: AudioComponent;
register: any;
play: any;
constructor(
private service: AudioService
) {
this.register = this.service.register;
this.play = this.service.getPlayers;
}
}
I want to create a dynamic tabs navigation system using Angular 2.
Basically I want to first display a single tab that contains a single component, containing clickable objects (like links, buttons...).
I would like that a click on one of those links adds a new tab, and that a click on each tab (the initial one and the newly created tab) displays a corresponding component in display zone (router-outlet) below.
This is what I've tried so far:
app.component.ts (Root component and "tabs container):
import { Component, OnInit } from '#angular/core';
import { TabComponent } from './tab/tab.component';
import { FirstComponent } from './test/first.component';
import { SecondComponent } from './test/second.component';
import { ThirdComponent } from './test/third.component';
import { ROUTER_DIRECTIVES } from '#angular/router';
#Component({
selector: 'my-app',
templateUrl: './app/app.component.html',
directives: [TabComponent, ROUTER_DIRECTIVES, FirstComponent, SecondComponent, ThirdComponent],
})
export class AppComponent implements OnInit{
tabList: any[];
constructor() {}
ngOnInit() {
this.tabList = [
{
name: 'link 1',
link: "/comp1"
},
{
name: 'link 2',
link: "/comp2"
},
{
name: 'link 3',
link: "/comp3"
}
]
}
}
app.component.html:
<h1>Tabs container</h1>
<div>
<nav>
<tab *ngFor="let tab of tabList" [name]="tab.name" [link]="tab.link"></tab>
</nav>
</div>
<div>
<router-outlet></router-outlet>
</div>
Each tab is represented by a tab.component.ts:
import { ROUTER_DIRECTIVES, Router } from '#angular/router';
import { Component, OnInit, Input } from '#angular/core';
#Component({
selector: 'tab',
templateUrl: './app/tab/tab.component.html',
directives: [ROUTER_DIRECTIVES]
})
export class TabComponent implements OnInit {
#Input() name: string;
#Input() link: string;
#Input() param: string;
targetArray: Array<any>;
constructor(private router: Router) {}
ngOnInit() {
}
}
which template is tab.component.html:
<a [routerLink]='link'>{{name}}</a>
Here is the app.routes.ts file:
import { provideRouter, RouterConfig } from '#angular/router';
import { TabComponent } from './tab/tab.component';
import { FirstComponent } from './test/first.component';
import { SecondComponent } from './test/second.component';
import { ThirdComponent } from './test/third.component';
export const routes: RouterConfig = [
{
path: '',
component: TabComponent
},
{
path: 'comp1',
component: FirstComponent
},
{
path: 'comp2',
component: SecondComponent
},
{
path: 'comp3',
component: ThirdComponent
},
];
export const APP_ROUTER_PROVIDERS = [
provideRouter(routes)
];
Here is for example the first.component.ts (SecondComponent and ThirdComponent are similar):
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'first',
template: `<h1>First</h1>
<button (click)="addTab()">Display child</button>
`
})
export class FirstComponent implements OnInit {
constructor() {}
ngOnInit() {
}
addTab(){
}
}
I would like to put the tab creation logic in the addTab() method to basically add an element to the tabList array in app.component.ts and obtain the desired behavior but I don't know how to transfer data from this component to the app.component.ts.
I also open to any different approach and suggestions.
You can inject the Router into your component and use the config method to configure dynamic links.
router.config([
{ 'path': '/', 'component': IndexComp },
{ 'path': '/user/:id', 'component': UserComp },
]);
The documentation for the Router service can be found here.