通过适当的更改跟踪将服务属性绑定到组件属性 [英] Bind a service property to a component property with proper change tracking

查看:20
本文介绍了通过适当的更改跟踪将服务属性绑定到组件属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑完全简单的 Angular 2 服务:

import { Injectable } from '@angular/core';从../models/Category.model"导入{Category};@Injectable()导出类 CategoryService {activeCategory: 类别|{} = {};构造函数(){};}

然后是使用这个服务的组件:

import { Component, OnInit } from '@angular/core';从../shared/services/category.service"导入{CategoryService};从../shared/models/Category.model"导入{Category};@成分({选择器:'我的选择器',模板:`{{categoryService.activeCategory.Name}}
{{category.Name}}<br/>`,})导出类 MySelectorComponent 实现 OnInit {类别:类别|{} = {};构造函数(公共类别服务:类别服务){};ngOnInit() {this.category = this.categoryService.activeCategory;};}

假设适当定义了类别模型,并假设某处的另一个组件将服务上的 activeCategory 设置为某个时候的有效类别.假设类别服务被设置为适当更高级别的提供者.

发生这种情况时,模板中的第一行将正确显示类别名称,但第二行不会.我试过在服务上使用 getter 和 setter 与原始访问;我尝试过原始类型与对象与对象属性;我不敢相信第一行是这种类型访问的适当范例.有人能告诉我将服务属性绑定到组件属性的最简单方法吗?

澄清:我知道我可以使用我自己创建和推送的 observables.我要问的是,是否有任何一种已经融入框架的方式来做到这一点(不需要我为一个可观察的对象编写大量的样板),它只是在服务和组件之间建立一个可变的轨道.

解决方案

Observables 可以使用 Behaviors ,而无需太多样板.

@Injectable()导出类 CategoryService {activeCategory:BehaviorSubject<{category:Category}>= new BehaviorSubject({category:null});//或者只是`Subject`,具体取决于您的要求}

@Component({选择器:'我的选择器',模板:`{{(categoryService.activeCategory | async)?.Name}}<br/>`,})导出类 MySelectorComponent 实现 OnInit {构造函数(公共类别服务:类别服务){};}

您也可以绑定到您的服务的属性

@Component({选择器:'我的选择器',模板:`{{categoryService?.activeCategory?.Name}}<br/>`,})导出类 MySelectorComponent 实现 OnInit {构造函数(公共类别服务:类别服务){};}

使用 Elvis(或安全导航)运算符,如果 activeCategory 仅在稍后获取值(例如异步调用完成时),则不会出现错误.

Consider the utterly simple Angular 2 service:

import { Injectable } from '@angular/core';
import {Category} from "../models/Category.model";

@Injectable()
export class CategoryService {
    activeCategory: Category|{} = {};
    constructor() {};
}

And then the component using this service:

import { Component, OnInit } from '@angular/core';
import {CategoryService} from "../shared/services/category.service";
import {Category} from "../shared/models/Category.model";

@Component({
    selector: 'my-selector',
    template: `
    {{categoryService.activeCategory.Name}}<br/>
    {{category.Name}}<br/>
`,
})
export class MySelectorComponent implements OnInit {
    category:Category|{} = {};

    constructor(public categoryService:CategoryService){};

    ngOnInit() {
        this.category = this.categoryService.activeCategory;
    };
}

Assume appropriately defined Category model and assume that another component somewhere sets the activeCategory on the service to a valid Category at some point. Assume that the categoryservice is set as provider at an appropriately higher level.

When that happens, the first line in the template will correctly display the category Name, but the second line will not. I've tried using getters and setters vs. raw access on the service; I've tried primitive types vs. objects vs. object properties; I can't believe that the first line is the appropriate paradigm for this type of access. Can someone tell me the simplest way to bind a service property to a component property that will properly do change tracking in angular two?

CLARIFICATION: I know I could use observables that I create and push to for myself. What I am asking is if there is any kind of already-baked into the framework way of doing this (that doesn't require me to write the huge amount of boilerplate for an observable) that just makes a variable track between the service and component.

解决方案

Observables can be used without much boilerplate using Behaviors.

@Injectable() 
export class CategoryService {
  activeCategory:BehaviorSubject<{category:Category}> = new BehaviorSubject({category:null});
  // or just `Subject` depending on your requirements
}

@Component({
  selector: 'my-selector',
  template: `
  {{(categoryService.activeCategory | async)?.Name}}<br/>
`,
})
export class MySelectorComponent implements OnInit {
  constructor(public categoryService:CategoryService){};
}

You also can just bind to properties of your service

@Component({
  selector: 'my-selector',
  template: `
  {{categoryService?.activeCategory?.Name}}<br/>
`,
})
export class MySelectorComponent implements OnInit {
  constructor(public categoryService:CategoryService){};
}    

Using the Elvis (or safe-navigation) operator you don't get an error if the activeCategory only gets a value later, for example when an async call completes.

这篇关于通过适当的更改跟踪将服务属性绑定到组件属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆