Data binding with polymer.dart

In the first recipe, we will go through an example that shows the complete mechanics of working with a Polymer component and data binding, and at the same time emphasizes some important best practices to work with polymer.dart. You can find the code in the project bank_terminal. The app creates an object of class BankAccount (which can be found in the lib folder) and populates it with the data that is shown. You can also provide a transaction amount and the balance of the account is updated. This is depicted in the following screenshot:

Data binding with polymer.dart

How to do it...

Perform the following steps to bind data with polymer.dart:

  1. First, install the polymer dependency in your project by adding polymer: ">=0.11.0 <0.12.0" to the pubspec.yaml file. Save the file in the editor and run pub get from the command line. This has to be accompanied by an import line; in webank_app.dart, we use import'package:polymer/polymer.dart'; but also in webank_app.html with a <link rel="import"> tag as the first line.
  2. Also, in that file, you must indicate one or more starting points of app execution in the transformers section, as shown in the following code:
    transformers:
    - polymer:
    entry_points:
    - web/bank_terminal.html
    - web/index.html
  3. The root folder of the app contains a build.dart file, with the following content:
    import'package:polymer/builder.dart';
    
    main() {     
      build(entryPoints: ['web/bank_terminal.html']);
    }
  4. The entry point bank_terminal.html must contain the <script> and <link> tags in the <head> section, in the following order:
    <script src="packages/web_components/platform.js"></script>
      <script src="packages/web_components/dart_support.js"></script>
    <!-- import the bank-app custom element -->
    <link rel="import"href="bank_app.html">
        <script type="application/dart">export 'package:polymer/init.dart';</script>
    <script src="packages/browser/dart.js"></script>
  5. The Polymer component with the name bank-app is instantiated in the <body> section of the same entry file:
    <bank-app></bank-app>
  6. The component is defined in bank_app.html as follows:
    <link rel="import"href="packages/polymer/polymer.html">
    <polymer-element name="bank-app">
    <style>
    .auto-style1 {
      width: 25%;
      border: 1px solid #0000FF;
    }
    
    .auto-style2 {
      width: 107px;
    }
    
    .btns {
      width: 127px;
    }
    
    .red {
      color: red;
    }
    </style>
    <template>
    <table class="auto-style1" on-keypress="{{enter}}">
    <tr>
    <td class="auto-style2">Number</td>
    <td>{{bac.number}}</td>
    </tr>
    <tr>
    <td class="auto-style2">Owner</td>
    <td>{{bac.owner.name}}</td>
    </tr>
    <tr>
    <td class="auto-style2">Starting balance</td>
    <td> {{bac.balance}}</td>
    </tr>
    <tr>
    <td class="auto-style2"> After transaction:</td>
    <td> {{balance}}</td>
    </tr>
    <tr>
    <td class="auto-style2">Amount</td>
    <td><input id="amount" type="text"/></td>
    </tr>
    <tr>
    <td>
    t</td>
    </tr>
    </table>
    </template>
    <script type="application/dart" src="bank_app.dart"></script>
    </polymer-element>
    
  7. The code of the Polymer component can be found in bank_app.dart:
    import'dart:html';
    import'package:polymer/polymer.dart';
    import'package:bank_terminal/bank_terminal.dart';
    
    @CustomTag('bank-app')
    classBankAppextendsPolymerElement {
      @observableBankAccountbac;
      @observable double balance;
      doubleamount = 0.0;
      
      BankApp.created() : super.created() { }
      
      @override
      attached() {
        super.attached();
        varjw = new Person("John Witgenstein");
        bac = newBankAccount(jw, "456-0692322-12", 1500.0);
        balance = bac.balance;
      }
      
      transact(Event e, vardetail, Node target) {
        InputElementamountInput = shadowRoot.querySelector("#amount");
        if (!checkAmount(amountInput.value)) return;
        bac.transact(amount);
        balance = bac.balance;
      }
      
      enter(KeyboardEvent  e, vardetail, Node target) {
        if (e.keyCode == KeyCode.ENTER) {
          transact(e, detail, target);
        }
      }
      
      checkAmount(String in_amount) {
        try {
        amount = double.parse(in_amount);
        } onFormatExceptioncatch(ex) {
        returnfalse;
        }
        returntrue;
      }
    }

How it works...

The actual numbers in step 1 for the polymer dependency may vary, but because the changes between versions can still be significant, it is better to use explicit versions rather than any other version here in order to not break your app; you can then also upgrade it when ready after thorough testing. The build.dart script in step 3 ensures that the project is built whenever a file in it is saved. The <link> tag in step 4 imports the Polymer element bank-app, which lives in bank_app.html. The platform.js and dart_support.js files contain the so-called platform polyfills; this is the JavaScript code to make new web standards such as custom elements, shadow DOM, template elements, and HTML imports work. They are called polyfills because at a later stage the browser should provide native code for these standards. The init.dart script starts up polymer.dart, and dart.js checks whether there is a Dart VM available to run the code directly. If this is not the case, the app runs from the compiled JavaScript code. Step 5 uses the name of the Polymer element as an HTML tag.

Step 6 comprises the HTML code for the Polymer component. It defines its style (in a <style> tag) and structure (within a <template> tag) between the <polymer-element> tags; its starting tag has the name of the component as an attribute, which is name="bank-app". We see how one-way data binding is achieved with the {{ … }} syntax of the polymer expression, as in <td>{{bac.number}}</td> or <td>{{bac.owner.name}}</td>. The dots between the curly braces take the place of a variable from the code, whose value is shown in that place in the web page. In the code, these variables are annotated with @published.Event. Interaction is achieved through declarative on-event = "{{ … }}" handlers, such as on-click="{{transact}}" in the button. Here, the dots stand for the name of a method in the code to be executed when the event happens. After <template>, the accompanying Dart script bank_app.dart is referenced through a <script> tag.

Finally, in step 7, we get to the Dart class that is backing up for our Polymer component and see the BankApp class extend PolymerElement; its class inherits from PolymerElement. The class declaration must be preceded by the annotation @CustomTag('bank-app') to associate it with the Polymer component. Variables that have to be visualized on the web page are annotated with @observable.

Override a custom element life cycle method such as attached to execute component-specific code. This method is executed when an element is inserted into the DOM; so it is a good place to initialize an app. It is obligatory to provide the created named constructor for your component. The constructor or any overridden method must call the superclass constructor or method first. The transact or enter method shows the signature for an event handler, enter(KeyboardEvent e, var detail, Node target). The transact method shows how we can get the value for an input element in our Polymer component; use the shadowRoot.querySelector method. After the format of the input amount is checked, the transact method of the class BankAccount in the bank_terminal library changes the state of the bac object.

The name of a Polymer component must contain at least one dash (-). Notice the naming scheme; if the name of the Polymer component is pol-comp1:

  • Then it is referenced in the HTML code as < pol-comp1>
  • It is defined in the files pol_comp1.html and pol_comp1.dart
  • Its class name is Polcomp1

There's more…

Polymer components can also be added dynamically via code, instead of being statically declared in the page's HTML. Suppose you want to add a component named pol-comp1 in a <div> tag with an ID of add-comp1. You can do this with the following code:

querySelector('#add-comp1').children.add(new Element.tag('pol-comp1'));

In step 3, you could call a linter instead of an ordinary build by replacing this line, as shown in the following code:

main(args) {
  lint(entryPoints: ['web/index.html'], options: parseOptions(args));
}

This will display more extensive syntax or usage warnings in your code.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset