5. NodeWire Web Applications

NodeWire supports web components created from html and NodeWire script. Semantic-Ui css styles can be applied to the html. Please refer to the semantic-ui documentation .

A NodeWire application is made of one or more layout files which can be either in xml format or in json format. Each layout must have a single top-level element and you will therefore need to use a container element such as div if you want to render more than one element.

To get you started go to Semantic-UI and copy any of the sample codes and past into your layout:

<button class="ui button">Follow</button>

Remember to enclose your elements in a div if you use more than one element:

<div>
  <button class="ui primary button">
    Save
  </button>
  <button class="ui button">
    Discard
  </button>
</div>
<div>
  <button class="ui primary basic button">Primary</button>
  <button class="ui secondary basic button">Secondary</button>
  <button class="ui positive basic button">Positive</button>
  <button class="ui negative basic button">Negative</button>
</div>

5.1. Adding interactivity

In order to make layouts interactive, we have to introduce nodes and ports. The special node ‘me’ will be used very often and it is a node that represents the browser instance. It will be used to save and retrieve values. But remember that where ever you see ‘me’ it can be replaced with any other node.

HTML Attributes can take their values from nodes and ports. This is done by using the nodename.portname, pref=ceded by “expr:”” as the string value of the attribute. In order to assign a value to our port, we will introduce the script tag.

The script tag allows you to write NodeWire scripts right inside the layout:

<div>
  <script>
    me.attribute = "ui red button"
  </script>
  <div class="expr:me.attribute">
    Click Me
  </div>
</div>

Now that we have replaced our hardcoded attributes with variables. We can modify them programatically. In order to do that we will need to use event handlers. Event handlers in NodeWire are specified by preceding an expression with “action:”, example: OnClick = “action:me.attribute=’ui blue button’”

<div>
  <script>
    me.attribute = "ui red button"
  </script>
  <div class="expr:me.attribute"
       when="me.attribute"
       onClick = "action:me.attribute='ui blue button'"
       >
    Click Me
  </div>
</div>

Note the special “when” attribute. It is used to monitor variables that should cause our ui element to redraw when they change.

<div class="ui labeled button" tabindex="0">
  <script>
    me.count = 0
  </script>
  <div class="ui red button"
       onClick="action:me.count=me.count+1">
    <i class="heart icon"></i> Like
  </div>
  <a class="ui basic red left pointing label"
     when="me.count" content="expr:me.count"
     onClick="action:me.count=0" />
</div>

You can monitor port values using a when block:

<div>
  <script>
    me.attribute = "ui red button"
    me.value = 0
    when me.value == 0:
      me.attribute = "ui red button"
    when me.value == 1:
      me.attribute = "ui green button"
  </script>
  <div class="expr:me.attribute"
       when="me.attribute"
       onClick = "action:me.value=1 if me.value==0 else 0"
       >
    Click Me
  </div>
</div>

5.2. Using time signals

The predefined time variable returns the number of seconds since Jan 1 1970. And it can be used to create when statements that are time based.

<div>
  <script>
    me.count = 0
    me.delay = time
    when time - me.delay >  0.1:
      me.delay = time
      me.count = me.count + 1
  </script>
  <b content="expr:me.count"  when="me.count" />
</div>

5.3. Input

Text

<div class="ui input">
  <script>
    me.value=''
  </script>
  <input type="text" change="me.value" value="expr:me.value" placeholder="Search..."/>
</div>

The change attribute binds (one way) a port to the value of the input. The binding is completed by assigning the same port to the value attribute.

CheckBox

<div>
  <script>
    when me.check == 1:
            me.visi = 'visibility: visible'
    when me.check == 0:
            me.visi = 'visibility: hidden'
  </script>
  <div class="ui checkbox">
    <input type="checkbox" name="example" change="me.check" value="me.check"/>
    <label>Make my profile visible</label>
  </div>
  <div style="expr:me.visi" when="me.visi">
    My Profile
  </div>
</div>

Radio Button

<div class="ui form">
  <div class="inline fields">
    <label>How often do you use checkboxes?</label>
    <div class="field">
      <div class="ui radio checkbox">
        <input type="radio" name="frequency" onClick="action:me.check=1" checked="expr:me.check==1" when="me.check"/>
        <label>Once a week</label>
      </div>
    </div>
    <div class="field">
      <div class="ui radio checkbox">
        <input type="radio" name="frequency" onClick="action:me.check=2" checked="expr:me.check==2" when="me.check"/>
        <label>2-3 times a week</label>
      </div>
    </div>
    <div class="field">
      <div class="ui radio checkbox">
        <input type="radio" name="frequency" onClick="action:me.check=3" checked="expr:me.check==3" when="me.check"/>
        <label>Once a day</label>
      </div>
    </div>
    <div class="field">
      <div class="ui radio checkbox">
        <input type="radio" name="frequency" onClick="action:me.check=4" checked="expr:me.check==4" when="me.check"/>
        <label>Twice a day</label>
      </div>
    </div>
  </div>
  <div content="expr:me.check" when="me.check"/>
</div>

5.4. Form

The special ‘submit’ attribute indicates where the form data should be stored. Each form field should have an id which will correspond to the the data field.

<div>
  <script>
    me.message = "ui success message hidden"
    when me.user:
      me.message = "ui success message"
  </script>
  <form class="ui form" submit="me.user">
    <div class="field">
      <label>First Name</label>
      <input type="text" id="firstname" placeholder="First Name"/>
    </div>
    <div class="field">
      <label>Last Name</label>
      <input type="text" id="lastname" placeholder="Last Name"/>
    </div>
    <button class="ui button" type="submit">Submit</button>
  </form>
  <div class="expr:me.message" when="me.message">
    <i class="close icon"></i>
    <div class="header">
      Your user registration was successful.
    </div>
    <p>Username: <span content="expr:me.user.firstname"/></p>
    <p>Lastname: <span content="expr:me.user.lastname"/></p>
  </div>
</div>

5.5. Form Validation

<div>
  <script>
    me.message = "ui success message hidden"
    me.valid_firstname = 'ui hidden red pointing label'
    me.valid_lastname = 'ui hidden red pointing label'
    when me.user:
      me.message = "ui success message" if me.valid_firstname==1 and me.valid_lastname==1 else "ui hidden message"
    when me.check_firstname==1:
      me.check_firstname=0
      me.valid_firstname = 0 if me.user.firstname == ''  else 1
    when me.check_lastname==1:
      me.check_lastname=0
      me.valid_lastname = 0 if me.user.lastname == ''  else 1
  </script>
  <form class="ui form" submit="me.user">
    <div class="field">
      <label>First Name</label>
      <input type="text"
             id="firstname"
             placeholder="First Name"
             change="me.user.firstname"
             value="expr:me.user.firstname"
             onBlur ="action:me.check_firstname=1"
      />
      <div
           class="expr:'ui red pointing label' if me.valid_firstname==0 else 'ui hidden label'"
           when="me.valid_firstname"
      >
          You must enter first name
      </div>
    </div>
    <div class="field">
      <label>Last Name</label>
      <input
             type="text"
             id="lastname"
             placeholder="Last Name"
             change="me.user.lastname"
             value="expr:me.user.lastname"
             onBlur ="action:me.check_lastname=1"
      />
      <div
           class="expr:'ui red pointing label' if me.valid_lastname==0 else 'ui hidden label'"
           when="me.valid_lastname"
      >
          You must enter last name
      </div>
    </div>
    <button class="ui button" type="submit">Submit</button>
  </form>
  <div class="expr:me.message" when="me.message">
    <i class="close icon"></i>
    <div class="header">
      Your user registration was successful.
    </div>
    <p>Username: <span content="expr:me.user.firstname"/></p>
    <p>Lastname: <span content="expr:me.user.lastname"/></p>
  </div>
</div>

5.7. Templates

Templates are useful for displaying data in a repeating pattern such as in a list or table. A NodeWire template is made of a container element which has an ‘iter’ attribute. This attribute specifies a variable that will be used to index an array of values. The content of the container will be repeated during rendering for each element in the attached port. Within the content the iter variable will be substituded with the index value. The item variable must be enclosed in braces {i}.

Templates can be nested by using distinct iter variables.

<div>
  <script>
    me.people = [{'name': 'Ahmad'}, {'name': 'Rashaad'}, {'name': 'Habeeb'}]
  </script>
  <div content="expr:me.people[0].name" page="pname"></div>
  <ul node="me" port="people" iter="i" >
    <li content="expr:me.people[{i}].name"/>
  </ul>
</div>

Dynamically Creating A List

<div>
    <script>
        me.people = ['One', 'Two', 'Three']
        when me.add:
          me.people = me.people + me.add
    </script>
    <div class="ui input">
        <input type="text" value="expr:me.value" change="me.value"/>
    </div>
    <a class="ui button" onClick="action:me.add=me.value">add</a>
    <ul node="me" port="people" iter="i" >
        <li content="expr:me.people[{i}]"/>
    </ul>
</div>

Tables

<div style="margin: 'auto'; width: '100%'; overflowX:'scroll'">
  <script>
    me.people = [{'name': 'Ahmad', 'age':10}, {'name': 'Rashaad', 'age':8}, {'name': 'Habeeb', 'age': 6}]
  </script>
  <table class="ui celled padded table" >
    <thead>
      <tr><th>SN</th>
      <th>Name</th>
      <th>Age</th>
    </tr></thead>
    <tbody node="me" port="people" iter="i">
      <tr>
        <td>
          {i}
        </td>
        <td content="expr:me.people[{i}].name"/>
        <td content="expr:me.people[{i}].age"/>
      </tr>
    </tbody>
  </table>
</div>

5.8. Components

You can use a layout as a component in another layout. To do that, just use the component layout’s name as a tag in the containing layout:

<div>
  <button.xml caption="one" color="blue"/>
  <button.xml caption="two" color="red" />
</div>

Attributes defined in the component, ‘caption’ and ‘color’ in this example, will be passed from the component declaration.

And here is the button.xml component:

<div class="ui {color} button" content="{caption}"/>

Inside the component, the inherited attributes will be used as substitute text to replace all occurence of the attribute: {color} and {caption} above.

5.9. Swapping Components

Components can be swapped at runtime. In order to do that, you will have to have previously marked the tag with a name:

<div>
    <div name="swap">
        <first.xml />
    </div>
    <div class="ui button" onClick="action:me.page.swap='second.xml'">Swap</div>
</div>

5.10. first.xml

<div>First</div>

5.11. second.xml

<div>Second</div>

5.13. Router