Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Table of Contents


Purpose

To demonstrate how to create an elementary component using the Coder DevTools

Prerequisites

The fixer-io-wrapper Elementary Component

We will create an elementary component called fixer-io-wrapper. Which is a component that uses the fixer.io webservice to get current and historical foreign exchange rates published by the European Central Bank. This component will have the following interface (input slots on the left and output slot on the right):

Create an Elementary Component

To create the elementary you should use the +webpackage-createElementary task from the DevTools:

Code Block
languagebash
themeMidnight
> grunt +webpackage-createElementary

Then, provide the name for the component, in this case fixer-io-wrapper and a short description if you want (e.g.: Elementary component for the fixer-io webservice).

If everything is okay you will get:

Code Block
languagebash
themeMidnight
Done, without errors.

Process finished with exit code 0

The grunt task will be executed and the file and folder structure for an elementary component will be created inside your webpackage folder as follows:

The newly created folder contains a demo and a docs folder and the following three files:

  1. fixer-io-wrapper.html: provides a template for the elementary component using Polymer code
  2. fixer-io-wrapper.js: contains the logic for the elementary component
  3. fixer-io-wrapper-style.html: contains CSS style definitions for the elementary component

In the background the manifest.webpackage file (located on the root level of your webpackage folder) has been modified. It includes some webpackage meta information and by the moment the elementary component with a slot definition of a slot "a".

Code Block
languagejs
themeMidnight
"elementaryComponents": [
  {
    "artifactId": "fixer-io-wrapper",
    "description": "Elementary component for the fixer-io webservice",
    "runnables": [
      {
		...
]

Slot Definitions

We continue the development process by specifying slots according to the interface defined above. We need 4 slots for this elementary component, three input slots and one output slot. Slots are defined using JSON. So we can copy the definition of slot a and paste it three times and then change the slot definitions as follows.

Code Block
languagejs
themeMidnight
firstline1
linenumberstrue
        "slots": [
          {
            "slotId": "base",
            "type": "string",
            "direction": [
              "input"
            ],
            "value": "EUR"
          },
          {
            "slotId": "date",
            "type": "string",
            "direction": [
              "input"
            ],
            "value": "latest"
          },
          {
            "slotId": "currencies",
            "type": "string",
            "direction": [
              "input"
            ],
            "value": "USD,GBP,JPY"
          },
          {
            "slotId": "rates",
            "type": "array",
            "direction": [
              "output"
            ]
          },
		  {
  			"slotId": "currenciesLabels",
			"type": "array",
		   	"direction": [
    			"output"
		  	]
		  }
        ]

Now we have

  • Three input slots with initial values and
  • One output slot which provides the output data of this elementary.

Check Generated Documentation

Too check the generated documentation (i.e.interface view and details), perform the following steps

  1. Start the embedded webserver using the +startWebserver grunt task available in the DevTools. 
  2. Check the automatically generated docs: http://localhost:8282/<webpackage-name>/fixer-io-wrapper/docs/

It should look as follows:

Changing the View of the Elementary (.html File)

Now we need to change the template of the component which provides the visual part of the elementary component. For our we need an input interface for the input slots (where you choose the currencies, base, date).

Open the fixer-io-wrapper.html file and edit the template to be as shown bellow:

Code Block
languagexml
themeMidnight
firstline1
linenumberstrue
<link rel="import" href="fixer-io-wrapper-style.html">
<dom-module id="fixer-io-wrapper">
    <template>
        <style include="fixer-io-wrapper-style"></style>
    <div>
      <form action="" on-submit="submit">
        <label>Base:</label>
        <input type="text" id="base">
        <label>Date:</label>
        <input type="text" id="date">
        <label>Currencies:</label>
        <input type="text" id="currencies">
        <input type="submit" value="submit">
      </form>
    </div>
    <div id="result">
      <table>
    	<tbody>
    		<tr>
        		<td>
            		Currency <br>
            		<template is="dom-repeat" items="{{model.currenciesLabels}}">
                		{{item}} <br>
            		</template>
        		</td>
        		<td>
            		<template is="dom-repeat" items="{{model.rates.0}}">
                		{{item}} <br>
            		</template>
        		</td>
    		</tr>
    	</tbody>
	  </table>
    </div>
    </template>
    <script src="fixer-io-wrapper.js"></script>
</dom-module>


To see the result check the automatically generated demo page to reflect the changes: http://localhost:8282/<webpackage-name>/fixer-io-wrapper/demo/

Change the Logic of the Elementary (.js File)

The file fixer-io-wrapper.js handles what will happen when a slot value is changed. We should modify the implementation in order to handle the three different input values and send the https-request to the fixer.io Webservice and receive the response.

We basically delete everything provided in the template file that is related to slot a because we want to use slots the slots we defined in last section.

Instead we add some code to be called whenever an input-slot has been changed (a new value is set) - on a method for each input-slot.

Finally we create a method to send a query to the fixer.io webservice (in our case the name is "sendQuery").

For now we won't change the CSS style definitions which are set in the file fixer-io-wrapper-style.html.

Open the file fixer-io-wrapper.js and change it according to the following code block:

Code Block
languagejs
themeMidnight
firstline1
linenumberstrue
(function() {
    'use strict';
    /**
     * Get help:
     * > Lifecycle callbacks:
     * https://www.polymer-project.org/1.0/docs/devguide/registering-elements.html#lifecycle-callbacks
 *    *
Access  the Cubbles   * Access the Cubbles-Component-Model:
     * > Access slot values:
     * slot 'a': this.getA(); | this.setA(value)
     */
    CubxPolymer({
        is: 'fixer-io-wrapper',

       		modelBaseChanged: function(newValue) { /**
         * Observe the 'base' slot //to update the view of 			this.$.base.setAttribute('value', newValue);this component and then
         * send  this.sendQuery();
   the request to the fixer-io api
    },     * @param {string} newValue modelDateChanged: function(newValue) {
  - new value of the slot
         *//
   update the view
			   modelBaseChanged: function(newValue) {
            // update the view
            this.$.datebase.setAttribute('value', newValue);

            this.sendQuery();
        },
        modelCurrenciesChanged: function(newValue) {/**
         * Observe the   //'date' slot to update the view of 			this.$.currencies.setAttribute('value', newValue);
  component and then
          this.sendQuery();
     * send the request to the fixer-io api
  },       *  submit: function(event) {
       @param {string} newValue - new value of the slot ('yyyy-mm-dd' format)
    event.preventDefault();     */
       this.model.base = this.$.base.value;
 modelDateChanged: function(newValue) {
           this.model.date = this.$.date.value;
  // update the view
          this.model.currencies = this.$.currenciesdate.setAttribute('value', newValue);

            this.sendQuery();
        },
        sendQuery: function() {/**
         * Observe the slot  // Makes sure all slots are defined
			if(this.getBase() && this.getCurrencies()) {
         'currencies' to update the view of this component
         * and then send the request to the fixer-io api.
      var baseUrl = '//api.fixer.io/';
           * @param {string} newValue - new value of the slot (coma separated
     var queryUrl = baseUrl + this.getDate(* currencies)
+  '?base=' +      */
              this.getBase() + '&symbols=' + this.getCurrencies();modelCurrenciesChanged: function(newValue) {
            // update the view
   console.log(queryUrl); 				 				var self = this;    this.$.currencies.setAttribute('value', newValue);

           var xhttp = new XMLHttpRequest this.sendQuery();
 				xhttp.onreadystatechange = function() {    },
				if (this.readyState == 4 && this.status == 200) {/**
        				var data = JSON.parse(xhttp.responseText);
				        console.log(data);
					 * Submit the form, update the Component-Model and then send the request
         * to the fixer-io api.
         * @param event
         */
        submit: function(event) {
            event.preventDefault();
            // Update the Cubbles component model slots the setters
            this.setBase(this.$.base.value);
            this.setDate(this.$.date.value);
            this.setCurrencies(this.$.currencies.value);

            this.sendQuery();
        },
        /**
         * Send the request a to the fixer-io api.
         */
        sendQuery: function() {
            // Makes sure all slots are defined
            if(this.getBase() && this.getCurrencies()) {
                var baseUrl = '//api.fixer.io/';
                var queryUrl = baseUrl + this.getDate() + '?base=' +
                    this.getBase() + '&symbols=' + this.getCurrencies();

                var self = this;

                var xhttp = new XMLHttpRequest();
                xhttp.onreadystatechange = function() {
                    if (this.readyState == 4 && this.status == 200) {
                        var data = JSON.parse(xhttp.responseText);
                        console.log(data);
                        var props = Object.getOwnPropertyNames(data.rates);
                        console.log(props);
                        var rates = ['Rate'];
                        var xLabels = [];
                        props.forEach(function(p) {
                            xLabels.push(p);
                            rates.push(data.rates[p]);
                        });
              var props = Object.getOwnPropertyNames(data.rates);     				  //  console.log(props);
				        var rates = ['Rate'];
				Update the Cubbles component model slots using the setters
            var xLabels = []; 			        propsself.forEachsetCurrenciesLabels(function(p) {xLabels);
                        			xLabels.push(p);
			self.setRates([rates]);
                   rates.push(data.rates[p]);
			 }
       }); 		        self.setCurrenciesLabels(xLabels);};
         		self.setRates([rates]);     			} 			}; 			xhttp.open("GET", queryUrl, true);
			
                xhttp.send();
            }
        }
    });
}());


Now when the value of a slot changes or the submit button is clicked, a request will be sent.

To check whether it works, reload the demo on the browser (http://localhost:8282/<webpackage-name>/fixer-io-wrapper/demo/) and the result will be displayed below the form, as follows:

Try another date using the yyyy-mm-dd syntax, for example "2015-11-12". The values for the currencies should change after clicking the submit button.