最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Angular 2 Shared Data Service is not working - Stack Overflow

programmeradmin7浏览0评论

I have built a shared data service that's designed to hold the users login details which can then be used to display the username on the header, but I cant get it to work.

Here's my (abbreviated) code:

// Shared Service
@Injectable()
export class SharedDataService {

    // Observable string source
    private dataSource = new Subject<any>();

    // Observable string stream
    data$ = this.dataSource.asObservable();

    // Service message mands
    insertData(data: Object) {
        this.dataSource.next(data)
    }
}

...

// Login ponent
import { SharedDataService } from 'shared-data.service';
@Component({
    providers: [SharedDataService]
})
export class loginComponent {
    constructor(private sharedData: SharedDataService) {}

    onLoginSubmit() {
        // Login stuff
        this.authService.login(loginInfo).subscribe(data => {
             this.sharedData.insertData({'name':'TEST'});
        }
    }
}

...

// Header ponent
import { SharedDataService } from 'shared-data.service';
@Component({
    providers: [SharedDataService]
})
export class headerComponent implements OnInit {
    greeting: string;

    constructor(private sharedData: SharedDataService) {}

    ngOnInit() {
        this.sharedData.data$.subscribe(data => {
            console.log('onInit',data)
            this.greeting = data.name
        });
    }
}

I can add a console log in the service insertData() method which shoes the model being updated, but the OnInit method doesn't reflect the change.

The code I've written is very much inspired by this plunkr which does work, so I am at a loss as to what's wrong.

Before posting here I tried a few other attempts. This one and this one again both work on the demo, but not in my app.

I'm using Angular 2.4.8.

Looking through different tutorials and forum posts all show similar examples of how to get a shared service working, so I guess I am doing something wrong. I'm fairly new to building with Angular 2 ing from an AngularJS background and this is the first thing that has me truly stuck.

Thanks

I have built a shared data service that's designed to hold the users login details which can then be used to display the username on the header, but I cant get it to work.

Here's my (abbreviated) code:

// Shared Service
@Injectable()
export class SharedDataService {

    // Observable string source
    private dataSource = new Subject<any>();

    // Observable string stream
    data$ = this.dataSource.asObservable();

    // Service message mands
    insertData(data: Object) {
        this.dataSource.next(data)
    }
}

...

// Login ponent
import { SharedDataService } from 'shared-data.service';
@Component({
    providers: [SharedDataService]
})
export class loginComponent {
    constructor(private sharedData: SharedDataService) {}

    onLoginSubmit() {
        // Login stuff
        this.authService.login(loginInfo).subscribe(data => {
             this.sharedData.insertData({'name':'TEST'});
        }
    }
}

...

// Header ponent
import { SharedDataService } from 'shared-data.service';
@Component({
    providers: [SharedDataService]
})
export class headerComponent implements OnInit {
    greeting: string;

    constructor(private sharedData: SharedDataService) {}

    ngOnInit() {
        this.sharedData.data$.subscribe(data => {
            console.log('onInit',data)
            this.greeting = data.name
        });
    }
}

I can add a console log in the service insertData() method which shoes the model being updated, but the OnInit method doesn't reflect the change.

The code I've written is very much inspired by this plunkr which does work, so I am at a loss as to what's wrong.

Before posting here I tried a few other attempts. This one and this one again both work on the demo, but not in my app.

I'm using Angular 2.4.8.

Looking through different tutorials and forum posts all show similar examples of how to get a shared service working, so I guess I am doing something wrong. I'm fairly new to building with Angular 2 ing from an AngularJS background and this is the first thing that has me truly stuck.

Thanks

Share Improve this question edited Mar 17, 2017 at 15:10 EJP asked Mar 17, 2017 at 15:04 EJPEJP 1814 silver badges13 bronze badges 1
  • if you put your service as a provider in any ponent, the constructor will be called each time. You probably want to have a unique instance of the entire service in your entire application. To acplish such, either inject the provider in the NgModule providers (in your app module), either inject the provider in the parent view and add it to viewProviders. In your case, though, it would be better to directly inject the service in the AppModule – briosheje Commented Mar 17, 2017 at 15:15
Add a ment  | 

3 Answers 3

Reset to default 7

This seems to be a recurring problem in understanding Angular's dependency injection.

The basic issue is in how you are configuring the providers of your service.

The short version: Always configure your providers at the NgModule level UNLESS you want a separate instance for a specific ponent. Only then do you add it to the providers array of the ponent that you want the separate instance of.

The long version: Angular's new dependency injection system allows for you to have multiple instances of services if you so which (which is in contrast to AngularJS i.e. Angular 1 which ONLY allowed singletons). If you configure the provider for your service at the NgModule level, you'll get a singleton of your service that is shared by all ponents/services etc. But, if you configure a ponent to also have a provider, then that ponent (and all its subponents) will get a different instance of the service that they can all share. This option allows for some powerful options if you so require.

That's the basic model. It, is of course, not quite so simple, but that basic rule of configuring your providers at the NgModule level by default unless you explicitly want a different instance for a specific ponent will carry you far.

And when you want to dive deeper, check out the official Angular docs

Also note that lazy loading plicates this basic rule as well, so again, check the docs.

EDIT:

So for your specific situation,

@Component({
    providers: [SharedDataService]  <--- remove this line from both of your ponents, and add that line to your NgModule configuration instead
})

Add it in @NgModule.providers array of your AppModule:

if you add it in @Component.providers array then you are limiting the scope of SharedDataService instance to that ponent and its children.

in other words each ponent has its own injector which means that headerComponentwill make its own instance of SharedDataServiceand loginComponent will make its own instance.

My case is that I forget to configure my imports to add HttpClientModule in @NgModules, it works.

发布评论

评论列表(0)

  1. 暂无评论