Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bind an Angular 2 expression and TypeScript method?

What I am trying to do is to show the full name, when first name and last name are entered.

This works:

<h1 [hidden]="!firstName || !lastName">Hello {{lastName + ', ' + firstName}}!</h1>

This does not work (what is the correct way of invoking a method defined in the class?):

<!--h1 [hidden]="!firstName || !lastName">Hello {{fullName()}}!</h1!-->

This does not work either:

<button ng-click="alertFullName()">show full name</button>

Here are the files: index.html:

<!DOCTYPE html>
<html>

  <head>
    <title>Angular 2 QuickStart</title>

    <!-- 1. Load libraries -->
    <script src="https://rawgithub.com/systemjs/systemjs/0.19.6/dist/system.js"></script>
    <script src="https://code.angularjs.org/tools/typescript.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.0/angular2-polyfills.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.0/Rx.js"></script>
    <script src="https://code.angularjs.org/2.0.0-beta.0/angular2.dev.js"></script>

    <!-- 2. Configure SystemJS -->
    <script>
      System.config({
        transpiler: 'typescript', 
        typescriptOptions: { emitDecoratorMetadata: true }, 
        packages: {'src': {defaultExtension: 'ts'}} 
      });
    </script>

    <!-- 3. Bootstrap -->
    <script>
      System.import('angular2/platform/browser').then(function(ng){
        System.import('src/hello_world').then(function(src) {
          ng.bootstrap(src.HelloWorld);
        });
      });
    </script>

  </head>

  <!-- 4. Display the application -->
  <body>
    <hello-world>Loading...</hello-world>
  </body>

</html>

src/hello_world.html:

<label>Name:</label>
<input type="text" [(ngModel)]="firstName" placeholder="Enter first name here">
<input type="text" [(ngModel)]="lastName" placeholder="Enter last name here">
<hr>
<h1 [hidden]="!firstName || !lastName">Hello {{lastName + ', ' + firstName}}!</h1>
<!--h1 [hidden]="!firstName || !lastName">Hello {{fullName()}}!</h1!-->
<button ng-click="alertFullName()">show full name</button>

src/hello_world.ts:

import {Component} from 'angular2/core';

@Component({
  // Declare the tag name in index.html to where the component attaches
  selector: 'hello-world',

  // Location of the template for this component
  templateUrl: 'src/hello_world.html'
})
export class HelloWorld {
  firstName: string = '';
  lastName: string = '';
  function fullName(): string {
    return firstName + ', ' + lastName;
  }
  function alertFullName() {
    alert(firstName + ', ' + lastName);
  }
}
like image 291
Peter Pei Guo Avatar asked Dec 23 '15 21:12

Peter Pei Guo


3 Answers

In addition to what @Günter Zöchbauer wrote (i.e., use (click), not ng-click), this code

function fullName(): string {
   return firstName + ', ' + lastName;
}
function alertFullName() {
  alert(firstName + ', ' + lastName);
}

should be

fullName():string {
    return this.firstName + ', ' + this.lastName;
}
alertFullName() {
   alert(this.firstName + ', ' + this.lastName);
}
like image 74
Mark Rajcok Avatar answered Nov 16 '22 10:11

Mark Rajcok


If we take a look at the documentation for Angular 2 templates we can see that interpolation in the form of {{bindMe}} can bind only to properties:

Expressions can be used to bind to properties only. Expressions represent how data should be projected to the View. Expressions should not have any side effect and should be idempotent.

This means the following example is 'illegal' as it represents a function invocation:

<h1 [hidden]="!firstName || !lastName">Hello {{fullName()}}!</h1>

You could instead have a getter fullName which produces the value you want:

export class HelloWorld {
  firstName: string = '';
  lastName: string = '';
  get fullName () {
      return firstName + ' ' + lastName;
  }
}

And then consume fullName in your template:

<h1 [hidden]="!fullName.length">Hello {{fullName}}!</h1>
like image 2
sdgluck Avatar answered Nov 16 '22 09:11

sdgluck


This

<button ng-click="alertFullName()">show full name</button>

should be

<button (click)="alertFullName()">show full name</button>

This works fine for me

<h1 [hidden]="!firstName || !lastName">Hello {{fullName()}}!</h1>

(I had to change the "!firstName || !lastName" expression because I use Dart and there the null check has to be explicit)

like image 1
Günter Zöchbauer Avatar answered Nov 16 '22 09:11

Günter Zöchbauer