Mobile Dev Course W3U3 Rewrite – XML Views – An Intro
I rewrote the mobile dev course sample app from W3U3. Then I created a new branch ‘xmlviews’ in the repo on Github and rebuilt the views in XML (they were originally in JavaScript). This post talks about XML views, and touches on some points that might be useful for you if you’re looking to build SAPUI5 apps with XML views yourself. See the links at the bottom of the opening post of this series to get to explanations for the other areas.
Different Ways To Define a View
To understand where XML views fit in, let’s take a look at this diagram that highlights the Model-View-Controller (MVC) support that SAPUI5 has.
Views can be written in JavaScript, HTML, JSON or XML.
- HTML: The Wave 1 Fiori apps are written in HTML (and may be re-written to be in XML)
- JavaScript: Many of us start out writing views in JavaScript, partially because there are a lot of examples out there in JavaScript (that’s changing soon with the sap.m Explored app in the DemoKit – watch this space!) and partially because it’s the same language we use to build the controllers
- JSON: You can build views declaratively with JSON; it’s not common to see, but intriguing nonetheless, especially when you consider building views programmatically
- XML: Fiori Wave 2 apps are built with XML views
Recently I’ve had a good chunk of work that involved writing XML views, and I can honestly say that in contrast to the received wisdom that has XML as “generally verbose and clunky”, writing views in XML is both concise and very pleasant, not to mention satisfyingly declarative.
A Simple View in XML and JavaScript
Let’s get an idea of what an XML view looks like, and contrast it with the JavaScript equivalent. We’ll keep it deliberately simple – this is what it looks like:
We’re using the sap.m library controls: An App, containing a Page, which has a Text as the only main content, and a Bar, containing a Button, as the footer.
This is what the view looks like declared in XML.
<core:View xmlns:core="sap.ui.core" xmlns="sap.m">
<App>
<Page title="Greetings">
<Text text="Hello World" />
<footer>
<Bar>
<contentRight>
<Button text="Edit" />
</contentRight>
</Bar>
</footer>
</Page>
</App>
</core:View>
And this is what it looks like declared in JavaScript. Note that I’ve deliberately avoided any unnecessary verbosity by not declaring intermediate variables to hold the different controls, as is common in many examples.
sap.ui.jsview("com.opensap.Page", {
createContent: function(oController) {
return new sap.m.App({
pages: [
new sap.m.Page({
title: "Greetings",
content: [
new sap.m.Text({
text: "Hello World"
})
],
footer: new sap.m.Bar({
contentRight: new sap.m.Button({
text: "Edit"
})
})
})
]
});
}
})
Now, this is not a competition between the two, but I know which I prefer. The XML view is simpler to scan and it’s clearer to see what controls are being used, and what relation they have to each other. It’s also slightly less verbose than the JavaScript view. This conciseness is accentuated with larger views – the concise nature of the declarative syntax remains and scales in XML.
The Nature of an XML View
XML Namespaces
Let’s have a look in a bit more detail at that XML view. Notice first that there are namespace definitions. This is standard XML stuff, and affords us prefixes to specify from what SAPUI5 library the specific control is from. Here we have a couple of prefix namespaces – “core”, for the sap.ui.core library, and the default namespace (no prefix) for the sap.m library. It makes sense in this case (and for the Fiori apps) to have the default namespace set for sap.m as that’s where the majority of the controls come from, and therefore the majority of the XML element names won’t need a prefix. Note the “core” prefix is used on the root element itself: “core:View”.
Representing Controls
Once we’ve declared our namespaces, we’re ready to declare the controls that we want to use. And for the App control, for example, it’s as simple as an opening and closing element pair: “<App>…</App>”. The same goes for all the other controls in this example too. Detail for a control is specified using XML attributes. For example, the Page has a title of “Greetings” and this is specified in an attribute, as is the text (“Hello World”) for the Text control.
Note that the controls we mentioned are represented by XML elements that are capitalised (View, App, Page, Text, Bar, Button).
Digging Into Controls
But what about the other stuff? What’s that “<footer>…</footer>”, for example? That’s not a control, nor is it capitalised. It’s an aggregation. Specifically, an aggregation belonging to the Page control.
Let’s take a step back and look at how controls are structured. We’ll take the sap.m.Page control as an example. This is what we see when we look at the sap.m.Page control’s constructor documentation in the API reference:
We see that a control can have Properties, Aggregations, Associations and Events. In this example, what we’re interested in are Properties and Aggregations. By now you will probably have worked out that Properties of a control are declared using XML attributes (title=”Greetings”, for example). And as properties don’t start with an uppercase letter, neither do the corresponding attribute names.
So that brings us on to Aggregations. An aggregation can be thought of as a collection of zero or more ‘child controls’. Perhaps one of the most common aggregations is in a sap.m.List control, where the entries in the list are, say, sap.m.StandardListItem control children in the ‘items’ aggregation. Note that in the aggregation definition, the type of controls that can be contained can be restricted. In the case of the List’s items aggregation, the type sap.m.ListItemBase is specified:
As sap.m.StandardListItem inherits from sap.m.ListItemBase, it is a valid control to be contained in the sap.m.List’s items aggregation.
So, back to “<footer>…</footer>”. Guess what? Yes, this XML element, with a lower case initial letter, represents an aggregation. You can see from the documentation screenshot that the footer aggregation of the sap.m.Page control expects a single control – a sap.m.Bar. So that’s what we have – a Bar. And in turn, the sap.m.Bar control has a triple of aggregations, representing content in the left, center and right of the Bar. In this case we want to put a sap.m.Button control on the right, so we use the contentRight aggregation. And the simplicity of what we want to do is in some part reflected in the simplicity of the XML:
<Page title="Greetings">
<Text text="Hello World" />
<footer>
<Bar>
<contentRight>
<Button text="Edit" />
</contentRight>
</Bar>
</footer>
</Page>
But wait. In the JavaScript version the sap.m.Text control is specified within the content aggregation of the sap.m.Page:
new sap.m.Page({
title: "Greetings",
content: [
new sap.m.Text({
text: "Hello World"
})
],
Where’s the equivalent in the XML? There isn’t. Or rather, it’s implicit. The content aggregation is the Page’s default aggregation, and as such, doesn’t need to be explicitly declared in the XML view. Clean! You can include the “<content> … </content>” if you want:
<Page title="Greetings">
<content>
<Text text="Hello World" />
</content>
<footer>
<Bar>
<contentRight>
<Button text="Edit" />
</contentRight>
</Bar>
</footer>
</Page>
but you don’t have to.
Next Steps
Armed with this knowledge, we’re ready to examine the XML versions of the views in the W3U3 app I rewrote. We’ll do that in the next post.
Until then, share & enjoy!
Hi DJ,
Thanks for putting this up - I was getting very frustrated with JS views but HTML and JSON views just didn't seem appropriate to me and I didn't think to really give XML a shot since it was so...XML like.
But after a little play, it seemed pretty intuitive and much easier to code, but I did run into one issue that I'm still confused about.
When creating a responsive design form using the sap.ui.layout.form objects; the associations don't seem to work as I would expect.
e.g. it is not recognising the formContainer association when I use this XML:
...
<form:Form
title="Test Form">
<formContainers>
...
It actually considers formContainers as a new object, and not an association.
I guess without debugging the SAPUI5 code, it's not clear how it works out the difference between associations and controls except the upper case/lower case statement plus in this case, it's genuinely not realising that formContainers is an association against a Form according to the API documentation.
FYI - I'm running SAPUI5 1.16.3.
So the real question then: how does it work out it's associations versus new API's?
And on a similar note - have you come across the related XSD's for all of this so you don't have to interpret the API documentation to understand the format, and potentially provide some form of validation/auto-complete?
Cheers,
Matt
Forgot to add; I added xmlns:form="sap.ui.layout.form" to provide the form: prefix in the above example...
Hi Matt
Thanks for the comment, and I agree about the intuitive nature of the XML views.
Without seeing the error message, it's hard to say, but from looking at the code snippet in what you describe, perhaps your issue is that you haven't prefixed the <formContainers> aggregation element with the form namespace. So your snippet should be:
<form:Form
title="Test Form">
<form:formContainers>
dj
Cool - That was it (though sure I tried that at one point). So in short, the XML parsing within an XML View keeps a track of where it is within the document to determine whether a tag is an aggregate before assuming it is a control and relies on the aggregate being in the same namespace (this implied logic kind of bugs me, but makes perfect sense now). I wrongly assumed the aggregate was independent of the namespace and was evaluated based on the previous control. (FYI - Tried debugging this in debug mode but there's a lot of code before it gets anywhere near parsing the XML file - e.g. Gave up).
Or put more simply - aggregates are implied within the XML document, but still need to be in the same namespace as the control which contains it.
Cheers,
Matt
ps. FYI - I learn by understanding how things work, but in the case of SAPUI5, there's a lot of leaps of faith I'm finding (e.g. Implicit links are the hardest to follow).
XSDs? That's a good question. I'll ask around to see if there's any plans in the pipeline.
dj
Very nice blog, it helped me a lot of understanding XML views. But i stll have a question. For example if you take a sap.m.table. The jsdoc says it has a aggreation called items but if you want to bind a model to the table all of a sudden items is a property, even if that property is not listed, that is a bit confusing me..
Example:
and so on. Could you explain how i can figure out where to place my bindings, that did cost me a lot of time 😉
Thanks
Regards
p.s. howto post code properly nowadays? {code} does not seem to work anymore..
Thanks Mathias. I'm not sure I understand this part of your sentence: "... if you want to bind a model to the table all of a sudden items is a property ...".
Items is an aggregation of sap.m.Table (via sap.m.ListItemBase), and will always be an aggregation. You can specify a binding in the XML attribute "items", but the aggregation in XML itself is signified by the lowercase element <items>.
Or did I misunderstand? Sorry if I did.
Regarding the code formatting, I know, the editor on SCN does leave a LOT to be desired. But your small snippet was still readable so it's OK 🙂
Let me clarify 🙂 The question i have is: Where in the documentations is writen that the binding property is called items(for sap.m.table) or rows(for sap.ui.table) Both have in the documentation only an aggregation(itmes/rows) but no properties with that name. That is the confusing part. I hope i clarified my problem?
Regards
Perhaps the confusion is over 'property'. To what are you referring when you say property? Taking sap.m.Table, the aggregation is 'items'. When using an sap.m.Table in an XML view this aggregation is brought to life by both the <Table> element's items attribute and also a child element of the <Table> element, namely <items>.
Hmm, sorry still don't get it. Where is the table items Attribute defined in the documentation?
I don't think there are any specific references to attributes in the API docu, but the API docu is independent, pretty much, of any view language. I picked the info up on XML view definitions from reading stuff in the developer guide and consuming as many examples as I could find. Hence I'm also sharing more examples for others to consume.
Thanks DJ. This is a great article. I've been battling through extending and developing apps the last few months and struggling to really understand how the API relates to the XML/Javascript I've been looking at. You've just made everything "click" into place. Wish I had read this a few weeks ago but nonetheless the struggle has made me appreciate this content so much more!
Hey, thanks for letting me know, glad to have been able to help!