I am using the following toastr implementation in my Angular 7 app: https://www.npmjs.com/package/ngx-toastr
I am trying to figure out on how can I make all the toasts append to the body, or other div element which will be in my root app component (I want to keep them displayed even in case where the component from which they are called will be destroyed).
Is there any way to archive it?
As the readme in your link already states, you need to provide your own ToastrContainer.
import {
ToastrModule,
ToastContainerModule // Add this one
} from 'ngx-toastr';
#NgModule({
declarations: [AppComponent],
imports: [
//...
ToastContainerModule // Add this one
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}
And add a div to your root component (or anywhere you want the container to be) like this:
#Component({
selector: 'app-root',
template: `
<h1><a (click)="onClick()">Click</a></h1>
<div toastContainer></div> <!-- Add this line here, above should be your router -->
`
})
export class AppComponent implements OnInit {
// Get a reference to the directive
#ViewChild(ToastContainerDirective) toastContainer: ToastContainerDirective;
constructor(private toastrService: ToastrService) {}
ngOnInit() {
// Register the container
this.toastrService.overlayContainer = this.toastContainer;
}
onClick() {
this.toastrService.success('in div');
}
}
Declare the module on your root module (usually app.module.ts)
import { ToastrModule } from 'ngx-toastr';
#NgModule({
imports: [ ToastrModule.forRoot({ ...global options... }) ],
...
})
The toasts can the be called for anywhere (granted you've injected the service in your component) and should be shown where you have defined them to be shown (and that no element covers them).
Related
It is first time To use Angular Now I'm learning angular 7:
- I create a new custom component in
- |src folder
---| app
----|| server (name of my component)
then I added in app.component.html the name of component
I see in the tutorial show in browser
the server component
even if he add it empty element
I do all steps in
server.component.ts file
import { Component } from '#angular/core';
#Component({
selector:'app-server',
templateUrl: './server.component.html'
})
export class ServerComponent {
}
& app.module.ts file
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppComponent } from './app.component';
import { ServerComponent } from './server/server.component';
#NgModule({
declarations: [
AppComponent,
ServerComponent
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Have you define your <app-server></app-server> somewhere?
For instance in the app.component.html
<app-navbar></app-navbar>
<app-server></app-server>
<app-footer></app-footer>
Also you will find an example here : https://angular.io/tutorial/toh-pt1
In your app.component.html add :
<app-server></app-server>
Thus you'll see its HTML.
What you did is in fact kind of import it and make it visible to other components declared in AppModule, but you didnt call it actually.
I have an Angular application in which I'd like to use a custom UrlResolver provider in order to add some cache breaking logic, as seen in this question (https://stackoverflow.com/a/43289767/868914).
However it doesn't seem that I can override the default compiler UrlResolver using a provider, as I would normally do and as the above link suggests.
Here is a plunker showing what I mean: https://plnkr.co/edit/zFsdyfNIoPcmbLO7WafW?p=preview
If you use the chrome (or other good) dev tools debugger to view the source for compiler.umd.js and search for the UrlResolver and put a break in the 'resolve' method, you can see the default implementation is being used instead of my provided class.
I cannot find a reason for this, hopefully someone on here knows a reason / solution?
Heres app.module code (as seen on the plunkr also)
//our root app component
import {Component, NgModule, VERSION} from '#angular/core';
import {BrowserModule} from '#angular/platform-browser';
import { UrlResolver } from "#angular/compiler";
#Component({
selector: 'my-app',
templateUrl: 'my-app.html',
})
export class App {
name:string;
constructor() {
this.name = `Angular! v${VERSION.full}`
}
}
class NewUrlResolver extends UrlResolver {
resolve(baseUrl: string, url: string): string {
console.log("Custom resolve");
return "rubbish";
}
}
#NgModule({
imports: [ BrowserModule ],
providers: [{
provide: UrlResolver, useClass: NewUrlResolver
}]
declarations: [ App ],
bootstrap: [ App ]
})
export class AppModule {}
You should provide your custom UrlResolver as part of providers in CompilerOptions when bootstraping application:
platformBrowserDynamic().bootstrapModule(AppModule, {
providers: [{ provide: UrlResolver, useClass: NewUrlResolver
}]})
Plunker Example
Below is a link to project on Plunker. where there are two components eager and lazy, also there is shared service which is used on both components.
How to update service variable in a module's component so that the variable in lazy module updates automatically?
[Plunker example][1]
[1]: https://plnkr.co/edit/L2ypUQZiltSPXnLlxBoa?p=preview
You have this behavior because of child injector created new instance of the service. For creating one instance of the service for application, you should use .forRoot() method
import { NgModule, ModuleWithProviders } from '#angular/core';
import { CommonModule } from '#angular/common';
import { SomeComponent } from './other.component';
import { SharedModule } from './shared/index'
import { SomeService } from './some.service';
#NgModule({
imports: [CommonModule, SharedModule],
declarations: [ SomeComponent ],
exports: [ SomeComponent ]
})
export class OtherModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: SharedModule,
// here you put services to share
providers: [SomeService]
}
}
}
// and in AppModule
#NgModule({
imports: [
CommonModule,
SharedModule,
OtherModule.forRoot()
],
declarations: [ SomeComponent ],
exports: [ SomeComponent ]
})
It will allow you to use one instance of SomeService in your components.
I've updated your plunker. Pleas, have a look on changed example
You can achieve this by using an Observable. This observable is stored in your service and other can subscribe to this observable. Below is an example in which I have removed the standard Angular stuff to improve readability:
service.ts
#Injectable()
export class MyService {
// BehaviorSubject sends last known value when someone subscribes.
public isAuthenticated$ = new BehaviorSubject<boolean>(false);
changeAuthenticated() {
// broadcast true to all subscribers
this.isAuthenticated$.next(true);
}
}
component.ts
myService.isAuthenticated$.subscribe(authenticated => {
if (authenticated) {
// do stuff
}
});
So when isAuthenticated$ inside MyService is changed it fires to all subscribers. Please not it doesn't fire if there are no subscribers.
More info about Observables: https://angular-2-training-book.rangle.io/handout/observables/using_observables.html
Hey I am new to angular 2, I have played with angular 2 for the past week and wondered if it possible to generate a dynamic component with a dynamic template and dynamic styles. This means that the follwoing should be like this
#Component({
// 2a
selector: 'dynamic placeholder',
// 2b
styles: [`dynamic styles`]
// 2c
template: `dynmic template`
})
is it possible to do it in angular 2, I remember that such this is maybe possible in angular 1.
Any Help will be appreciated(Escpecially plunkers with simple code)
This is what I have achieved so far: try using ComponentFactoryResolver:
#NgModule({
imports: [BrowserModule],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule {
}
#Component({
selector: 'my-app',
template: `
<div>Hello, world!</div>
`
})
export class AppComponent {
}
#NgModule({
declarations: [HomeComponent],
exports: [HomeComponent]
})
export class HomeModule {
}
#Component({
selector: 'home',
template: `
<div>This is home</div>
`
})
export class HomeComponent {
}
#Component({
selector: 'hello-world',
template: `
<div>
Hello, world!, {{name}}
The answer is: {{getAnswer()}}
</div>
`
})
export class HelloWorldComponent implements AfterViewInit {
private name:string = 'You';
constructor(private helloWorldService: HelloWorldService) {
}
ngAfterViewInit(): void {
this.name = 'Me';
}
private getAnswer() {
return this.helloWorldService.giveMeTheAnswer();
}
}
#NgModule({
declarations: [HomeComponent, HelloWorldComponent],
providers: [HelloWorldService],
exports: [HomeComponent]
})
export class HomeModule {
}
#Component({
selector: 'home',
template: `
<button (click)="sayHello()">Say hello</button>
<div>This is home</div>
`
})
export class HomeComponent {
constructor(private componentFactoryResolver: ComponentFactoryResolver,
private viewContainerRef: ViewContainerRef) {
}
private sayHello() {
const factory = this.componentFactoryResolver.resolveComponentFactory(HelloWorldComponent);
const ref = this.viewContainerRef.createComponent(factory);
ref.changeDetectorRef.detectChanges();
}
}
Here is a plunker which enables to created dynamic component, I don't know if creating dynamic css is possible,I would be pleased if some can I answer my question:
http://plnkr.co/edit/ZXsIWykqKZi5r75VMtw2?p=preview
With TypeScript and latest version of Angular2 (I believe that feature has been released in 2.4.0) you can create 1 base component and then extend it. All decorators/annotations on properties (#Input/#Output/#ViewChild) will be copied. However, you must specify for each ancestor #Component properties, i.e. you cannot overwrite only selector, but everything. That is RIGHT approach.
Another approach -> use reflect-metadata to update decorators on Component classes (probably that is what you are looking for, as it that case you can overwrite 1 property at time), but be careful to export (i.e. make public) all Components/Directives/Services that are used inside of Component that you want to overwrite. For example, some libraries have multiple Components, and some of them are supposed to be used only internally (i.e. there is no way to import it into your module in normal way... however, you can try providers). If you try to "overwrite", say, css with reflect-metadata and it uses internal components -> angular/typescript will crash, as it cannot resolve "internal" stuff. You can start with this answer: StackOverflow
I have an app module and single component application (made to demonstrate my problem), and getting following error:
Error in ./AppComponent class AppComponent_Host - inline template:0:0 caused by: No provider for UserService! ; Zone: <root> ; Task: Promise.then ; Value:
code for AppModule:
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { UserService } from './components/common/userservice';
#NgModule({
imports: [
BrowserModule,
],
declarations: [
AppComponent
],
providers: [UserService],
bootstrap: [AppComponent],
entryComponents: []
})
export class AppModule {
}
Code for my AppComponent:
import { Component} from '#angular/core';
import { UserService} from './userservice';
#Component({
selector: 'App',
template: `<h3>App component</h3>
user name: {{userName}}
`,
providers: []
})
export class AppComponent {
userName: string;
constructor(userService: UserService) {
this.userName = userService.userName;
}
}
My UserService Code:
import { Injectable, EventEmitter } from '#angular/core';
#Injectable()
export class UserService {
obs$: EventEmitter<any> = new EventEmitter<any>()
userName = 'Sherlock Holmes';
}
Now if i add UserService as provider to AppComponent, it will solve the issue. but i dont want to, because i want only one instance of my service in whole application. Even in subModules(feature modules).
according to my understanding, if i add service as provider on module level, then i can just inject it to any component under module.
here is am example i was watching.
Plunker
am using angular2 version: "2.0.0"
The import path is wrong: you use /Common in one and /common right below.
Visual Studio and WebStorm will not show IntelliSense errors for case-sensitivity of paths.
Furthermore, if using Angular 5's AoT template compilation, you can get a "This component is not part of a module" error, even though it is, because the import path is incorrect. Without AoT this will work, so you'll get a surprise when converting to AoT.
Remove your service: UserService from app.module.ts, then add in component:
#Component({
selector: 'App',
template: `<h3>App component</h3>
user name: {{userName}}
`,
providers: [UserService]
})
Hope this will help you.
An additional reason for getting this error - I duplicated a service to a different directory and was updating each file individually. Even though the first file still existed I got this error until I updated app.module.ts.