Search code examples
dartdart-polymer

Build Polymer App with multiple elements using one single Dart script


Do you know how to use multiple "polymer-element" with only one Dart script ?

I succeeded but I am not sure it is the best solution.

My example is a Dart/Polymer implementation of this following example with Dart/WebUI: https://www.dartlang.org/articles/web-ui/#loops

It displays a list of fruits in a polymer-element ("example-template1"), and where we can research a specific fruit in another polymer-element ("example-template2"). The second polymer-element must update the first with data binding.

To do that, I declared as follow my polymer elements. One parent polymer-element named "example-script" (because we can only use one script declaration in a polymer templates file), and children that extend from this parent :

<polymer-element name="example-script">
  <script type="application/dart" src="tute.dart"></script>
</polymer-element>

<polymer-element name="example-template1" extends="example-script">
  <template>
    <div>
      <p>Search fruit</p>
      <input type="text" class="form-control" value="{{ research }}" on-input="{{ get_results }}">
    </div>
  </template>
</polymer-element>

<polymer-element name="example-template2" extends="example-script">
  <template>
    <div><ul>
      <template repeat="{{ fruit in fruits }}">
        <li>{{ fruit }}</li>
      </template>
    </ul></div>
  </template>
</polymer-element>

My Dart script is as follow:

import 'package:polymer/polymer.dart';
import 'dart:html';

@CustomTag('example-script')
class FruitsScript extends PolymerElement {
  static List<String> fruitsList = new List();

  @observable static List<String> fruits = toObservable(fruitsList);
  @observable static String research = '';

  FruitsScript.created() : super.created();
}

@CustomTag('example-template1')
class FruitsResearch extends FruitsScript {
  FruitsResearch.created() : super.created();

  String get research {
    return FruitsScript.research;
  }

  String set research(String search) {
    FruitsScript.research = search;
  }

  void get_results(Event e, var detail, Node target) {
    FruitsScript.fruits.clear();

    if (FruitsScript.research.length > 0) {
      var lResearch = FruitsScript.research.toLowerCase();
      var results = FruitsScript.fruitsList.where((v) => v.toLowerCase().contains(lResearch));
      FruitsScript.fruits.addAll(results);
    }
    else {
      FruitsScript.fruits.addAll(FruitsScript.fruitsList);
    }
  }
}

@CustomTag('example-template2')
class FruitsDisplay extends FruitsScript {
  FruitsDisplay.created() : super.created() {
    List<String> fruits = [ 'Apple', 'Apricot', 'Avocado'];

    FruitsScript.fruitsList.clear();
    FruitsScript.fruitsList.addAll(fruits);
    FruitsScript.fruitsList.sort();
    FruitsScript.fruits.clear();
    FruitsScript.fruits.addAll(FruitsScript.fruitsList);
  }

  List<String> get fruits {
    return FruitsScript.fruits;
  }
}

I declare one parent Class "FruitsScript" to initialize the observable variables. Then, I create two other classes for my two polymer elements "example-template1/2". Hence I can access to my observable variables. But for that, I also need to declare them as static, and to make setters an getters in my subclasses, otherwise my polymer elements can not share the observable variables.

This method works, but do you think there is a better way to make this?


Solution

  • How do you add those elements to your page? As far as I understand what you want to to, inheritance (extend) is not the appropriate solution. I have not tried to run this code just edited your code here in the textfield. If this is what you want to do but something doesn't work post a comment. I didn't want to put to much time in it as long as it's not clear what exactly you want to achieve.

    In your web page you lay out your elements like this:

    <example-template1></example-template1>
    <example-template2></example-template2>
    <example-script></example-script>
    

    Your elements

    <polymer-element name="example-script">
      <script type="application/dart" src="tute.dart"></script>
    </polymer-element>
    
    <polymer-element name="example-template1">
      <template>
        <div>
          <p>Search fruit</p>
          <input type="text" class="form-control" value="{{ model.research }}" on-input="{{ get_results }}">
        </div>
      </template>
    </polymer-element>
    
    <polymer-element name="example-template2">
      <template>
        <div><ul>
          <template repeat="{{ fruit in model.fruits }}">
            <li>{{ fruit }}</li>
          </template>
        </ul></div>
      </template>
    </polymer-element>
    

    Your Dart script is as follow:

    import 'package:polymer/polymer.dart';
    import 'dart:html';
    
    class Model extends Object with Observable {
      @observable List<String> fruits = toObservable(new List<String>());
      @observable String research = '';
    }
    
    @CustomTag('example-script')
    class FruitsScript extends PolymerElement {
      @published Model model = new Model();
    
      FruitsScript.created() : super.created();
    
      void attached() {
        super.attached();
        (document.querySelector('example-template1') as FruitsResearch).model = model;
        (document.querySelector('example-template2') as FruitsDisplay).model = model;
      }
    }
    
    @CustomTag('example-template1')
    class FruitsResearch extends PolymerElement {
      FruitsResearch.created() : super.created();
    
      @published Model model;
    
      void get_results(Event e, var detail, Node target) {
        if (this.research.length > 0) {
          var lResearch = this.model.research.toLowerCase();
          var results = this.model.fruits.where((v) => v.toLowerCase().contains(lResearch));
          this.model.fruits = toObservable(results);
        }
      }
    }
    
    @CustomTag('example-template2')
    class FruitsDisplay extends PolymerElement {
      @published Model model = new Model();
    
      FruitsDisplay.created() : super.created() {
        this.model.fruits = toObservable([ 'Apple', 'Apricot', 'Avocado']);
        this.model.fruits.sort();
      }
    }