Application Sample

Editing Documents

Lets again review the WebTML code for the view mode, now highlighting some other parts:

<tml:range context="name:addresses">
    <tml:if haschildren="true">
        <tml:then>
            <ul>       
                <tml:children sortexpression="{portlet.sortitem||'lastname'}"
                                sortorder="ascending">
       
                    <li>
                        <a href="<tml:url
                                ajax="true"
                                portletmode="edit"
                                portletcontext="this"/>
">
                            <tml:meta name="title"/>
                        </a>
                        <button ...>
                            Delete
                        </button>   
                       
                    </li>       
                </tml:children>       
            </ul>
        </tml:then>
        <tml:else>
             ...
        </tml:else>
    </tml:if>
    ...
</tml:range>

The code begins with the tag <tml:range context="name:addresses">.

This causes the body of the <tml:range> tag to be rendered "in the context of" the document we specified in the "context" attribute, named "addresses". Remember the last chapter: A storage document of id "addresses" is defined in the model. This does nothing else but change the context to this "addresses" storage and let the tag contents of <tml:range> be rendered with it in context.

The <tml:children> tag is a navigator iterating over all child documents of the current context, then putting out its own content once in the context of each child document. As we know from the model definition the child documents of the "adresses" storage are "address" contents. So what we do here ist iterate over all address documents and put out a single data line for each one of them.

In the <tml:children> tag we use the attribute sortexpression="{portlet.sortitem||'lastname'}" to sort the child collection.

The sort expression itself is also dynamically calculated, this time using the curly braces "{}" directly. This means that the whole contents of the attribute is a TMLScript expression which should be used to calculate the attribute value.

Here the expression returns either the item of name "sortitem" stored in the portlet storage (which may have been stored by the <tml:input> tag discussed earlier) or the item name "lastname" if the portlet has no such item yet.

For each document in the storage "addresses" we create an <li> containing a link to URL

<tml:url ajax="true" portletmode="edit" portletcontext="this"/>

This link expresses a way to call an action when the user clicks on a link.

Again we do not specify an action here (which would be done using an "action" attribute) but we specify portletmode="edit" which will let the portlet be reloaded in "edit" mode. So this time WebTML module "mode-edit" will have its appearance.

In addition to that we have the new attribute portletcontext="this". This is to change the context of the reloaded portlet, which we will have a closer look at.

The Portlet Context

Portlets are normally rendered with the document in context that the WebTML tag including it already had in context . This is either a context given to it from some surrounding tag which explicitly chooses a special context (for example: <tml:children> or any tag having a "context" attribute) or a document which was explicitly addressed in the URL of the request. In the situation of this portlet this is no document at all, because <tml:portlet> in "main.tml" neither is contained in a tag choosing a context, nor is the request URL addressing a document.

However the code of the "view" mode explicitly selects context documents internally, first in <tml:range context="name:addresses"> where the context is changed to the storage document, then by <tml:children> which executes its tag content in the context of every single address document.

By using attribute "portletcontext" you can specify a document which the portlet should have in context when it is reloaded. Specifying "this" means that the document currently in context of the executed code will be this portlet context. In the current case this will be the concrete address document for which the URL is generated.

This altogether means, that not only WebTML module "mode-edit" is rendered but also that its code will have direct access to the address document which was selected. Or speaking "in WebTML" the portlet has the address document "in context".

So lets have a look at the WebTML code in "html/addresses/mode-edit.tml":

<h2>...</h2>

<tml:form id="edit-address" source="content">
   
    <tml:include ref="::form"/>   
    <hr>
    <tml:button clickaction="$store" ajax="true" portletmode="view">Update address</tml:button>
    <tml:button ajax="true" portletmode="view" portletcontext="none">Cancel</tml:button>

</tml:form>

This code looks very similar to the code the discussed for TML "mode-new".

We include the same "::form" module and have the same cancel-button.

The difference to "mode-new" is that the <tml:form> tag specifies source="content". This lets the form load all input field data from the document currently in context. It also lets default action $store save the form data back to the document it was loaded from.


Continue on next page ...