简体   繁体   English

角度5:服务在组件之间(跨模块)共享数据吗?

[英]Angular 5: Service to share data between Components (across Modules)?

I have this simple Service which is a provider in two Modules: 我有这个简单的服务,它是两个模块的provider

@Injectable()
export class PlatformPickerService {
  platforms: string[] = [
    'macOS', 'Linux', 'Windows'
  ];
  public platform: string;

  constructor() {
    this.platform = this.platforms[1];
  }

  public getPlatform(): string {
    const platform = localStorage.getItem('platform');
    return platform == null ? this.platform : platform;
  }

  public setPlatform(platform: string) {
    this.platform = platform;
    localStorage.setItem('platform', platform);
  }
}

Unfortunately, nowhere I use it acquired the chosen value. 不幸的是,我在任何地方都没有使用它获得选定的值。 Using it outside its Module gives only the default value, using it inside its Module gives no value. 在模块外使用它仅提供默认值,在模块内使用它不提供默认值。

Full test-case: https://stackblitz.com/edit/angular-aru94g-2djexv 完整的测试用例: https : //stackblitz.com/edit/angular-aru94g-2djexv

Services are singletons within the scope of an injector. 服务是注入器范围内的单例。 Define the PlatformPickerService as provider in app module or root module and make it as singleton service. 在应用程序模块或根模块中将PlatformPickerService定义为提供程序,并将其设置为单例服务。 This will be application scoped singleton service. 这将是应用程序范围内的单例服务。

Ok, Issue with your PlatformPickerComponent. 好的,发布您的PlatformPickerComponent。 You have to send the selected value to updateService. 您必须将所选值发送到updateService。

  • Property Binding -[] => Component to Template -- one way binding, Changing value doesn't update the property in component 属性绑定-[] =>组件到模板-一种方法绑定,更改值不会更新组件中的属性

    [value]="platformSelected" [value] =“ platformSelected”

  • Event Binding - () => Template to component 事件绑定-()=>模板到组件

    (change)="updateService($event.value)" (change)=“ updateService($ event.value)”

  • PlatformPickerService moved to app module for this example and set as application scoped provider. 在此示例中,PlatformPickerService移至应用程序模块,并设置为应用程序范围的提供程序。

Please check the sample app and demo . 请检查示例应用程序演示

Default platform value set in PlatformPickerService whenever change this it is reflected in drop down box as selected value. 在PlatformPickerService中设置的默认平台值每更改一次都会在下拉框中反映为所选值。

  constructor() {
    this.platform = this.platforms[4];
  }

Finally got it working: https://angular-aru94g-w6qy21.stackblitz.io ( edit ) 终于成功了: https : //angular-aru94g-w6qy21.stackblitz.io编辑

Major changes were: 主要变化是:

Component 零件

updateService(event: any) {
    if (event.value != null) this.platformPickerService.setPlatform(event.value);
}
<mat-form-field>
  <mat-select placeholder="Platform" shouldLabelFloat="false"
              [(ngModel)]="platformSelectd"
              (selectionChange)=updateService($event)>
    <mat-option *ngFor="let platform of platformPickerService.platforms"
                [value]=platform>
      {{ platform }}
    </mat-option>
  </mat-select>
</mat-form-field>

Module 模组

  • Only have PlatformPickerService in one Module (app.module) 在一个模块(app.module)中仅具有PlatformPickerService

Now it's time to try rewriting the setters/getters once more and see if that'll work ( setPlatform to set platform ) =3 现在是时候再次尝试重写setters / getters了,看是否行得通( setPlatform set platform )= 3

You've missed two-way binding in the PlatformPickerComponent Add import of FormsModule into the PlatformPickerModule and change the PlatformPickerComponent as below: 您已经错过了PlatformPickerComponent的双向绑定。将FormsModule导入添加到PlatformPickerModule ,并按如下所示更改PlatformPickerComponent

<mat-form-field>
  <mat-select placeholder="Platform" shouldLabelFloat="false" [(ngModel)]="platform">
    <mat-option *ngFor="let platform of platformPickerService.platforms"
                [value]="platform">
      {{ platform }}
    </mat-option>
  </mat-select>
</mat-form-field>



import {AfterViewInit, Component, OnInit} from '@angular/core';

import {PlatformPickerService} from './platform-picker.service';

@Component({
  selector: 'platform-picker',
  templateUrl: './platform-picker.component.html',
  styleUrls: ['./platform-picker.component.css']
})
export class PlatformPickerComponent implements OnInit, AfterViewInit {
  private _platform: string;

  constructor(public platformPickerService: PlatformPickerService) {
  }

  ngOnInit() {
    this._platform = this.platformPickerService.getPlatform();
  }

  ngAfterViewInit() {
  }

   get platform(): string {
    return this._platform;
  }

  set platform(value: string) {
    if (value != null) {
      this.platformPickerService.setPlatform(value);
      this._platform = value;
    }
  }
}

I made couple of changes to your existing code. 我对您现有的代码做了几处更改。 If you are using two way binding then you can skip ngModelChange Otherwise use oneway binding along with ngModelChange as follows. 如果您使用双向绑定,则可以跳过ngModelChange,否则,请按以下方式与ngModelChange一起使用单向绑定。

<mat-form-field>
  <mat-select [ngModel]="selected" (ngModelChange)="updateService($event)"  placeholder="Platform" shouldLabelFloat="false" [(value)]="selected">
    <mat-option *ngFor="let platform of platformPickerService.platforms"
                [value]="platform">
      {{ platform }}
    </mat-option>
  </mat-select>
</mat-form-field>

and you updateService function as follows 并且您的updateService函数如下

updateService(newPlatform) {
    console.log(newPlatform);
    if (newPlatform != null) {
      this.selected = newPlatform;
      this.platformPickerService.setPlatform(this.selected);
    }
  }

you can check the code here https://angular-aru94g-agtn1m.stackblitz.io 您可以在这里查看代码https://angular-aru94g-agtn1m.stackblitz.io

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM