【问题标题】:Angular 4 how can a directive listen for changes of a property in injected serviceAngular 4指令如何监听注入服务中属性的变化
【发布时间】:2017-07-10 10:53:21
【问题描述】:

我正在使用 Angular 4 构建一个应用程序,我有一个带有以下模板的组件:

<input
    [value]="myService.myValue"
    >

其中 myService 是注入到组件中的服务:

@Injectable()
    export class MyService {

    public myValue: string; // I could use an RxJS observable/Subject here
}

我需要添加一个指令(或其他东西)来监听 myValue 的变化并更改输入文本的颜色。

我该怎么做?有什么想法吗?

谢谢!

【问题讨论】:

  • 为什么不在服务中使用get 访问器属性?这真的很简单,而且很有效。

标签: angular rxjs directive


【解决方案1】:

创建一个共享服务,这样当myValue 发生变化时,您可以聆听它并应用您想要的任何逻辑。

服务:

@Injectable()
export class MyService {
    updateMyValue$: Observable<any>;

    private updateMyValueSubject = new Subject<any>();

    constructor() {
        this.updateMyValue$ = this.updateMyValueSubject.asObservable();
    }

    updateVal(newVal) {
        this.updateMyValueSubject.next(newVal);
    }
}

改变值的组件:

this.myService.updateVal('new value');

监听值变化的组件:

this.myService.updateMyValue$.subscribe(
        (newVal) => {
              this.inputValue = newVal; // I called `inputValue` to the variable that will contain the value of the input. It should be initialized.
              // Here we can apply our own logic such as change color, hide some DOM elements or whatever we need to do
        }
    );

说明:

第一个组件是将新值发送到服务,在我们的例子中是"new value"

第二个组件订阅了这个Subject,一旦触发next(),它就会接收新数据。换句话说,这个组件正在监听updateVal()函数,一旦触发它就会接收数据。

这是一种非常可靠且实用的组件间通信方式。

【讨论】:

    【解决方案2】:

    您可以使用 ngClass 或 ngStyle 如下

    <input [value]="myService.myValue" 
           [ngStyle]="{'color': myService.myValue === 1 ? 'red' : 'blue'}">
    

    ngClass

    <input [value]="myService.myValue" 
           [ngClass]="{'color-red': myService.myValue === 1, 'color-blue' : myService.myValue === 2}">
    

    检查这个 plnkr

    https://plnkr.co/edit/2IAxwnXOaWS4TUL7aov0?p=preview

    【讨论】:

      【解决方案3】:

      我找到了解决办法:

      <input [myDirective]="myService.parameter" myServiceValue="{{myService.value}}" ... >
      
      
      @Directive({
        selector: '[myDirective]'
      })
      export class parameterDirective implements OnInit, OnChanges {
        @Input('myDirective') parameter: parameter;
        @Input() myServiceValue: string;
      
        constructor(private el: ElementRef, private renderer: Renderer) {
        }
      
        ngOnInit(): void {
        }
      
        ngOnChanges(changes: SimpleChanges): void {
          switch (this.parameter) {
            case parameter.EnumValue:
              this.renderer.setElementClass(this.el.nativeElement, "my-class", changes.myServiceValue.currentValue > 100);
              break;
            default:
          }
      
        }
      }
      

      【讨论】:

        【解决方案4】:

        一个主题对于你正在谈论的内容来说太过分了。一般来说,反应性的主题应该谨慎使用。

        您可以使用简单的get 访问器完成您想要的操作

        export class MyService {
          myValue_: string;
          get myValue() {
            return this.myValue_;
          }
        }
        

        如果您还希望值流向另一个方向,您可以添加一个 set 访问器,尽管最好避免这样做,因为直接查看您的服务类会有点讨厌。

        【讨论】:

          猜你喜欢
          • 2018-04-24
          • 2016-07-15
          • 1970-01-01
          • 2017-05-16
          • 2023-02-08
          • 2019-09-29
          • 2019-10-07
          • 1970-01-01
          相关资源
          最近更新 更多