将ngModel与自定义组件一起使用

时间:2016-05-01 22:00:49

标签: typescript angular

简单地说,我想将Switch组件双向绑定到服务中的布尔值

这样的事情:

@Component({
    selector: 'my-switch',
    template: '...'
})

export class Switch {
    @Input() state: Boolean

    toggle() {
        if (this.state) {
            this.state = false
        } else {
            this.state = true
        }
    }
}

@Injectable()

class export FooService {
    theBoolean: Boolean
}

@Component({
    selector: 'my-app',
    template: '<my-switch [(state)]="_foo.theBoolean"></my-switch>{{ _foo.theBoolean }}'
})

export class App {
    constructor(private _foo: FooService) {}
}

那么这里应该发生的是,当切换开关时,FooService中的onChanges事件应该触发,反之亦然。

3 个答案:

答案 0 :(得分:3)

要使双向绑定生效,您需要声明一个名为'stateChange'的输出事件

@Output stateChange: EventEmitter<Boolean>=new EventEmitter();

然后在你的切换实现中:

toggle() {
    if (this.state) {
        this.state = false;
    } else {
        this.state = true
    }
    this.stateChange.emit(this.state);
}

在您的HTML模板中:

 [(state)]="model"

相当于:

 [state]="model"  (stateChange)="model=$event"

其中$ event是传递给EventEmitter的emit方法的参数。每当状态发生变化时,它会发出stateChange事件,然后更新父组件中的模型 - 从而使模型保持同步

答案 1 :(得分:0)

您还可以尝试以下

在组件开关中将FooService类型的变量foo定义为@Input(),并将App的foo属性传递给Switch Component su

@Component({
    selector: 'my-app',
    template: '<my-switch [foo]="_foo"></my-switch>{{ _foo.theBoolean }}'
})

export class App {
    constructor(private _foo: FooService) {}
}

export class Switch {
    @Input() foo: Foo

    toggle() {
        this.foo.theBoolean = !this.foo.theBoolean;
}

这样,App和Switch之间只共享一个FooService实例。因此,对它的任何更改(由App或Switch获得)都会反映在另一个组件上。

我希望这会有所帮助

答案 2 :(得分:0)

您还可以注意到,您可以通过利用自定义值访问器轻松实现符合ngModel / ngControl的自定义组件。通过这种方式,您可以使用ngModelngControl / ngFormControl按部分格式(验证,值)制作您的组件,如下所示:

<my-switch [(ngModel)]="_foo.theBoolean"
           #ctrl="ngModel" ngControl="switch"></my-switch>

以下是实现此目的的方法:

const SWITCH_VALUE_ACCESSOR = new Provider(NG_VALUE_ACCESSOR, { useExisting: forwardRef(() => Switch), multi: true});

@Component({
  selector: 'my-switch',
  template: '...'
})
export class Switch implements ControlValueAccessor {
  state: boolean;

  onChange = (_) => {};
  onTouched = () => {};

  writeValue(value: any): void {
    this.state = value;
  }

  toggle() {
    if (this.state) {
        this.state = false
    } else {
        this.state = true;
    }
    this.onChange(this.state);
  }

  registerOnChange(fn: (_: any) => void): void { this.onChange = fn; }
  registerOnTouched(fn: () => void): void { this.onTouched = fn; }
}

有关详细信息,请参阅此链接: