-1

I have a component that use controlvalueaccessor to bind ngModel passed form parent component

password.component.ts:

     import {
  Component,
  ElementRef,
  forwardRef,
  HostListener,
  Input,
  OnChanges,
  OnInit,
  SimpleChanges
} from "@angular/core";
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms";
export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => PasswordComponent),
  multi: true
};
@Component({
  selector: "app-password-input",
  templateUrl: "./password.component.html",
  styleUrls: ["./password.component.scss"]
})
export class PasswordComponent
  implements OnInit, ControlValueAccessor, OnChanges {
  _model: string;
  @Input() depended: string = "";
  @Input() name: string = "password";
  @Input() id: string = "password";
  @Input() class: string = "form-control";
  @Input() placeholder: string = "";
  @Input() required:boolean;

  setPassword(event) {
    this.writeValue(event);
  }

  changeModel() {
    this.model = "aaaa";
  }
 change(event){
    console.log("event",event);
    
  }
  constructor() {}
  ngOnChanges(changes: SimpleChanges): void {}
  ngOnInit(): void {}

  get model() {
    return this._model;
  }

  set model(val) {
    this._model = val;
    this.propagateChange(this._model);
  }

  writeValue(value: any) {
    if (value !== undefined) {
      this.model = value;
    }
  }

  propagateChange = (_: any) => {};

  registerOnChange(fn: any): void {
    this.propagateChange = fn;
  }

  registerOnTouched(fn: any): void {}

  setDisabledState?(isDisabled: boolean): void {}
}

and blow line is my password.component.html:

<div>
  <label for="password"
    >pass
    <small class="text-danger">*</small>
  </label>
  <div class="input-group mb-2">
    <input
      [class]="class"
      [id]="id"
      name="name"
      [(ngModel)]="model"
      #models="ngModel"
      (ngModelChange)="change($event)"
      [required]="required"
      [placeholder]="placeholder"
    />
    <div class="input-group-prepend">
      <button class="btn  rounded-0" (click)="changeModel()" type="button">
        change
      </button>
    </div>
  </div>
  in child component: {{model}}
</div>

and below is my parent component :

<app-password-input [(ngModel)]='password' name="password" ngDefaultControl></app-password-input>
out:
{{password}}

my problem is that when i change input with button that trigger changeModel model in password component is updating but value not affected to model.password in parent component

stack blitz link

1
  • The @Input() is a one-way data binding. To change the parent data from your child, you need a two-way data binding via an @Output(). Please read the answer here. Commented Mar 3, 2021 at 14:08

1 Answer 1

1

You need to provide NG_VALUE_ACCESSOR token to custom component inorder to binding work properly

@Component({
  selector: "app-password-input",
  templateUrl: "./password.component.html",
  styleUrls: ["./password.component.scss"],
  providers:[CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR]
})

Forked Working Example

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.