【问题标题】:How to detect shared data service changes for all components in Angular 9?如何检测 Angular 9 中所有组件的共享数据服务更改?
【发布时间】:2020-12-24 04:38:31
【问题描述】:

我正在使用自定义库做一个 Angular 应用程序。 有几个嵌套组件。

在子组件中,我单击一个按钮以从表单中设置新数据。

<button ... (click)="createFile()" >Create file</button>

child.component.html

<form [formGroup]="starterFormArray" *ngIf="starterFormWithStepper">
     <mat-horizontal-stepper #stepper>
         <mat-step *ngFor="let step of starterFormSteps; let index = index; let last = last;">
             <ng-template matStepLabel>{{ step.label }}</ng-template>
             <formly-form
                      [form]="starterFormArray.at(index)"
                      [model]="starterModel"
                      [fields]="step.fields"
                      [options]="starterOptions[index]">
              </formly-form>
         </mat-step>
     </mat-horizontal-stepper>
     <div class="wrapper-actions-for-stepper">
          <div class="part-toolbar">
              <button mat-stroked-button (click)="goBack(stepper)" type="button" [disabled]="stepper.selectedIndex === 0">Back</button>
              <button mat-stroked-button (click)="goForward(stepper)" type="button" [disabled]="stepper.selectedIndex === starterFormSteps.length-1">Next</button>
          </div>
          <div class="part-toolbar">
              <button mat-raised-button [disabled]="!starterFormArray.valid" (click)="createFile()" >Create file</button>
          </div>
      </div>
  </form>

子组件函数CreateFile()在共享数据服务中设置一个var

child.component.ts

@Component({
  selector: 'foo-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.scss'],
  providers:  [ DataService, provideParent( ParentComponent, BaseComponent  ) ]
})

export class ChildComponent extends BaseComponent implements OnInit, AfterViewInit, AfterViewChecked, AfterContentInit {

     starterForm: FormGroup;
     starterFormArray: FormArray;
     starterModel: CurrentProject;
     starterFormFields: Array<FormlyFieldConfig>;
     starterFormSteps: Array<StepType>;
     starterOptions: any;
     starterFormWithStepper: boolean;

     constructor(elRef: ElementRef, data: DataService ) {
         super(elRef);
         this.sharedData = data;
     }

     createFile() {
          this.sharedData.changeUserFile( this.starterModel );
     }
}

sharedData 参数在BaseComponent 中声明。

base.component.ts

import {DataService} from '../../common/services/data.service';

export class BaseComponent{
    public sharedData: DataService;
}

在我的共享服务中,我尝试采取一种方法来检测所有使用它的组件的任何更改。

data.service.ts

@Injectable()
export class DataService{
    public file: BehaviorSubject<CurrentProject> = new BehaviorSubject(null);
    public changeFile = this.file.asObservable();
    
    constructor( public cdref: ChangeDetectorRef ) {}

    changeUserFile( newData: CurrentProject ){
        this.file.next(newData);
        alert(JSON.stringify( this.file.getValue())); //<-- it works !
        this.cdref.detectChanges();
    }
}

parent.component.ts 从未检测到更改。

parent.component.ts

@Component({
    selector: 'foo-parent',
    templateUrl: './parent.component.html',
    styleUrls: ['./parent.component.scss'],
    encapsulation: ViewEncapsulation.None,
    providers:  [ DataService, provideParent( ParentComponent ) ]
})
export class ParentComponent extends BaseComponent implements OnInit, OnChanges{
      
     @Input() fileName: string;
      
      constructor(elRef: ElementRef, data: DataService, private cdref: ChangeDetectorRef ) {
           this.sharedData = data;
      }

      ngOnInit() {
          super.ngOnInit();
          this.sharedData.changeFile.subscribe( ( fileModified) => {
              if ( ( fileModified !== null ) && ( fileModified.getFileName() !== this.fileName ) ) {
                  alert('Never Called');
                  this.fileName = fileModified.getFileName();
              }
          }); 
      }
      ngOnChanges(changes: SimpleChanges) {
          alert('change only when the page is loaded');
      }
}

由于某些原因,parent.component.ts 无法实现数据,this.sharedData.changeFile.subscribe() 不起作用。 我测试了ngOnChangesChangeDetectorRef 没有成功。

有人知道这个问题吗?

【问题讨论】:

  • 您是说您没有看到从父组件订阅发送到 changeFile 流的任何值?更改检测与您的问题无关。

标签: angular detection angular-services


【解决方案1】:

每个组件都是一个类的另一个实例。扩展不会使它们共享相同的值,但服务会被实例化一次,并且在服务模块范围内的任何地方都可以通过在构造函数中注入来访问相同的实例。

简单的解决方案是注入 DataService 并订阅它,这将指向您应用中任何地方的相同 ref。

例如伪代码:

数据服务

class DataService {
  public file: BehaviorSubject<CurrentProject> = new BehaviorSubject(null);

  setDataMethod(newData: CurrentProject) {
    this.file.next(newData);
  }
}

ParentComp

class ParentComp extends BaseComp implements OnInit{
   constructor(private (or public to access from html) dataService: DataService) {}
   
   ngOnInit(){
     this.dataService.file.subscribe(changedFile => {
        //do stuff
     })
   }
}

或 DataService 位于提供程序中的同一模块内的任何其他相关/不相关子组件

class ParentComp extends BaseComp implements OnInit {
   constructor(private (or public to access from html) dataService: DataService) {}
   
   ngOnInit(){
     this.dataService.file.subscribe(changedFile => {
        //do stuff
     })
   }
}

【讨论】:

猜你喜欢
  • 2017-04-15
  • 2017-04-02
  • 2019-08-03
  • 2020-06-18
  • 1970-01-01
  • 1970-01-01
  • 2023-01-23
  • 2017-01-04
  • 2017-11-06
相关资源
最近更新 更多