Creating the web_links project

Get the code with git clone git://github.com/dzenanr/web_links.git command. We start our discussion with the first spiral in the web_linksweb_links_s01 project.

Spiral s01

In this spiral, we just show a web component that contains a list of links of the String type, as shown in the following screenshot:

Spiral s01

Spiral s01 of web_links

The webindex.html start up HTML page imports the web component with:

     <link rel="import" href="packages/web_links/links_app.html">

The component with the links-app name is instantiated in the <body> tag of the page:

    <links-app></links-app>

The liblinks_app.html file contains the UI definition of the component:

<link rel="import" href="../../packages/web_links/link_list.html">
<polymer-element name="links-app">
  <template>
    <link-list></link-list>
  </template>
  <script type="application/dart" src="links_app.dart"></script>
</polymer-element>

This in its turn imports a <link-list> web component defined in link_list.html:

<polymer-element name="link-list">
  <template>                                            (1)
    <ul>
      <template repeat="{{link in links}}">            (2)
        <li>
          <a href="{{link}}">                               (3)
            {{link}}
          </a>
        </li>
      </template>
    </ul>
  </template>
  <script type="application/dart" src="link_list.dart"></script> (4)
</polymer-element>

The outer template in line (1) is required. The template in line (2) uses a repeat statement to iterate over the links: repeat="{{link in links}} list. The link variable takes on the value of each list item in succession, and is shown through {{link }} in the next line. The list is constructed in the link_list.dart script referenced in line (4):

import 'package:polymer/polymer.dart';
@CustomTag('link-list')
class LinkList extends PolymerElement {
  List links =
    ['http://ondart.me/',
     'https://www.dartlang.org/polymer-dart/'];
  LinkList.created() : super.created();
}

Spiral s02

Now, we will base the web component on a model with one simple concept: a web link. This has two attributes: a name and a url. The Link class is defined in libmodellinks.dart:

class Link {
  String name;
  Uri url;
  Link(this.name, String link) {
    url = Uri.parse(link);
  }
}

It is a best practice to put our model in its own links library in a separate lib folder. The Polymer framework is based on the statement: everything is a component. We use a <links-app></links-app> web component in index.html that encapsulates the user interface and is also imported through a <link> tag <link rel="import" href="packages/web_links/links_app.html">. We show all our links as a <link-list> component in links_app.html, so the <link-list> component is embedded in <links-app>:

<link rel="import" href="../../packages/web_links/view/link_list.html">
<polymer-element name="links-app">
  <template>                
    <link-list links="{{links}}"></link-list>                (1)
  </template>
  <script type="application/dart" src="links_app.dart"></script>
</polymer-element>

This component in its turn is defined in viewlink_list.html and viewlink_list.dart.

Tip

Name the definition files of the web component like the component, replacing - with _ . This keeps a more complex project with different components structured.

In the links_app.dart file, we find the code for the <links-app> component that constructs a links collection called links:

import 'package:web_links/web_links.dart';
import 'package:polymer/polymer.dart';
@CustomTag('links-app')
class LinksApp extends PolymerElement {
  var links = toObservable(new List<Link>());
  LinksApp.created() : super.created() {
    var link1 = new Link('On Dart', 'http://ondart.me/'),
    var link2 = new Link('Polymer.dart' 'https://www.dartlang.org/polymer-dart/'),
   var link3 = new Link('Books To Read', 'http://www.goodreads.com/'),
    links..add(link1)..add(link2)..add(link3);            (2)
  }
}

Our <links-app> component is now instantiated through the template in line (1) in the preceding code; it needs a links variable, which is made in the LinksApp constructor in line (2).

The web component in link_list.html also uses the repeating template introduced in spiral s01, but now shows the names of the links:

     <template repeat="{{link in links}}">
        <li>
          <a href="{{link.url.toString()}}">
            {{link.name}}
          </a>
        </li>
     </template>

The link_list.dart file now also imports our model from the links library and annotates the links variable with @published in line (3) to show its contents:

import 'package:web_links/web_links.dart';
import 'package:polymer/polymer.dart';
@CustomTag('link-list')
class LinkList extends PolymerElement {
  @published List<Link> links;                             (3)
  LinkList.created() : super.created();
}

When you run the preceding code, it will look like the following screenshot:

Spiral s02

Spiral s02 of web_links

Apart from some added style in spiral s03, the <links-app> component is identical to the one in spiral s02.

Spiral s04

In this spiral, we will also provide the possibility to add a web link by the user:

Spiral s04

Adding a web link

A new link has to be shown; in order to accomplish this, we have to mark the list with toObservable in the links_app.dart file:

  var links = toObservable(new List<Link>());

The definition of the web links component in the link_list.html file now contains additional UI markup in its <template> tag to enable us to add links:

     <div>
        <label for="name">Name</label>
        <input id="name" type="text"/>
        <label for="url">web Link</label>
        <input id="url" type="text"/><br/>
        <button on-click="{{add}}" class="button">Add</button> (1)
        <label id="message"></label>
     </div>
    <ul> <!-- repeating template --> </ul></template>
    <script type="application/dart" src="link_list.dart"></script>

The add method from line (1) is found in the link_list.dart script:

add(Event e, var detail, Node target) {                        (2)
    InputElement name = shadowRoot.querySelector("#name");     (3)
    InputElement url = shadowRoot.querySelector ("#url");
    LabelElement message = shadowRoot.querySelector ("#message");
    var error = false;
    message.text = '';
    if (name.value.trim() == '') {
      message.text = 'name is mandatory; ${message.text}';
      error = true;
    }
    if (url.value.trim() == '') {
      message.text = 'web link is mandatory; ${message.text}';
      error = true;
    }
    if (!error) {
      var weblink = new Link(name.value, url.value);
      weblinks.add(weblink);                               (4)
    }
  }

Notice how in line (1) the add event handler is called in {{ }}. In line (2), we can see that it has three arguments: the third one is a direct reference to the target element on which the event happened. In line (3) and the ones that follow, we see how to get a reference to the inner markup of a web component. The familiar querySelector method call is now preceded by shadowRoot:

    shadowRoot.querySelector("#name");

Spiral s05

In spiral s05, we add the functionality to store our web links in the local storage by adding the code needed to load and save data to the model. The save functionality is implemented in the link_list.dart script of the <link-list> component. In the preceding code, after line (4), we will now add:

if (!error) {
  // previous code
   save();
}

We will then add this save method:

save() {
  window.localStorage['web_links'] = JSON.encode(toJson());
}

We want to save our data in the JSON format. To do this, our Link model class needs to know how to transform itself in a Map (with a toJson method) or to construct itself from a Map (using the Link.fromJson constructor):

Map<String, Object> toJson() {
    var linkMap = new Map<String, Object>();
    linkMap['name'] = name;
    linkMap['url'] = url.toString();
    return linkMap;
}

Link.fromJson(Map<String, Object> linkMap) {
    name = linkMap['name'];
    url = Uri.parse(linkMap['url']);
}

Spiral s06

The constructor LinksApp() method in links_app.dart first creates a list in line (4), and then calls the load() method in line (5) to read the data from the local storage:

   var links = toObservable(new List<Link>());            (4)
LinksApp.created() : super.created() {
  load();                                                 (5)
}

load() {
  String json = window.localStorage['web_links'];
  if (json == null) {
    init();                                               (6)
  } else {
    fromJson(JSON.decode(json));                          (7)
  }
}

If nothing was stored yet, the Model object is initialized via the init() method in line (6), otherwise, it is parsed from local storage in line (7). In line (4), the List object of links is created. As there is only one model object, we can safely refer to the unique links object of model to feed links within the web component's Dart code.

In spiral s06, the possibility is added to remove links, as shown in the following screenshot:

Spiral s06

Removing a web link

To allow this, a second button is placed inside the <template> tag of the <link-list> component:

<button on-click="{{delete}}" class="button">Remove</button>

The delete method is implemented in the script of the link_list.dart component:

  delete(Event e, var detail, Node target) {
    InputElement name = shadowRoot.querySelector("#name");
    InputElement url = shadowRoot.querySelector ("#url");
    LabelElement message = shadowRoot.querySelector("#message");
    message.text = '';
    Link link = links.find(name.value);
    if (link == null) {
      message.text = 'web link with this name does not exist';
    } else {
      url.value = link.url.toString();
      if (links.remove(link)) save();
    }
  }
..................Content has been hidden....................

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