2

In Angular2 I have a very simple form:

Form.ts

import {Component, Input} from 'angular2/core'

@Component({
  selector: 'my-form',
  providers: [],
  template: `
    <form>

      {{ details }}

      <input type="text" placeholder="name" />
      <input *ngIf="details" type="text" placeholder="details" />
    </form>
  `,
  directives: []
})
export class MyForm {

  @Input() details: bool;

  constructor() {

  }
}

As shown in this Plunkr, when I toggle the details @input via the button, the text changes between true and false.

However the *ngIf isn't toggling the textfield at all.

Any thoughts on what I miss here?

App.ts

import {Component} from 'angular2/core'
import {MyForm} from './form'

@Component({
  selector: 'my-app',
  providers: [],
  template: `
    <div>
      <button (click)="toggle()">toggle details</button>
      <my-form details="{{visible}}"></my-form>
    </div>
  `,
  directives: [MyForm]
})
export class App {

  visible: boolean = false;

  constructor() {
    this.name = 'Angular2'
  }

  toggle() {
    this.visible = !this.visible;
  }
}

2 Answers 2

3

You should use the following instead:

<my-form [details]="visible"></my-form>

instead of

<my-form details="{{visible}}"></my-form>

This allows to use property binding, i.e. one way binding (by reference). This means that when the provided expression changes, the sub component can see the update.

In your case, you simply intialize the input of the sub component with the value of the expression visible using interpolation. But then your sub component won't see updates.

Moreover in your case, you provide a string and not a boolean. Only property binding allows to provide types different than string...

See the working plunkr: https://plnkr.co/edit/z7rKGb6mLdLNj2jtSlcU?p=preview.

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

2 Comments

A small additional question: If I have e.g. 100 instances of my form and want each button to toggle the matching textbox. What is the best practice for this? I have created a Plunkr example at plnkr.co/edit/n8TZjpQgjg1YH7TefPkM?p=preview
"you simply initialize the input of the sub component with the value of the expression visible using interpolation. But then your sub component won't see updates." -- Not true. The child component will see updates when {{}} binding is used. It's just that {{template_expression}} binding always converts the template_expression to a string, then that string result is assigned to the input property. See Günter's answer.
1

Use instead

<my-form [details]="visible"></my-form>

Plunker

<my-form details="{{visible}}"></my-form>

passes 'true' to visible (stringifies). With [details] the unmodified value is passed. Therefore this form has to be used if you want to pass anything different than a string.

1 Comment

Why was this downvoted? (I just upvoted it). This answer is more correct than Thierry's.

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.