Monthly Archives: August 2015

The origin of becoming a fundamental enabler for Fiori

30 Days of UI5 - Day 30 by Sam Yen, Chief Design Officer, SAP

Not too long ago, before Fiori was Fiori, SAP had tried several times to refresh the user experience.  I’m aware of over 20 different UI technologies that we have used since the release of R/3.  As mobility was sweeping into the enterprise, SAP adopted a native mobile development approach.  At the time, many believed that this was an opportunity to create modern experiences with modern UI technologies (primarily iOS at the time) and development environments to refresh the SAP User Experience.

The first mobile apps showed promise, but as we started to roll out more and more, quality suffered.  The experience of some of the native apps were good, some bad.  We noticed a lot of creativity in building different ways to do the same things.  This came to a head when some of our large customers evaluated SAP’s mobile app portfolio as a whole and were not happy about this experience.

Design consistency was one thing.  Also, we considered the full lifecycle of these apps. Currently, there are over a thousand permutations of android software and hardware configurations in the market today.  Even Apple now has several versions of screen sizes and resolutions to support from tablets, phones, and now watches.  Cost of development, support, and ownership pointed to a modern, but scalable approach.  We made a decision to go with a responsive HTML5 approach.

Luckily, SAP had been developing HTML5 controls at that time.  As with other HTML5 libraries at the time, UI5 was separated between the desktop controls and the mobile controls.  We took the decision to combine the best of what we had and create a responsive UI5 control set for Fiori.

I may have understated the part about our customers being unhappy about the user experience.  It was escalated to the highest levels and we were under tremendous pressure to demonstrate to customers that this new concept would fly – quickly.  We had 6 days, 144 hours to be exact, to demonstrate to internal stakeholders the both the desirability and feasibility of our approach.  I’ll never forget Stefan Beck and the UI5 team walking down the halls of Walldorf to our war room saying that, “the UI5 team will support you.”

section1-1That was the beginning.  Since then UI5 and the team behind the technology have expanded much beyond a mere set of controls.  The team has helped to develop a programming model that is open and designed to scale for the enterprise.  It is part of growing set of tools to make UI development both efficient and scalable both for SAP and the industry.

Looking forward we’ll start to augment our responsive design approach to also leverage native, on-device capabilities.  Analytics will become more of an area of focus.  I have said many times that I feel my role as Chief Design Officer is to change the perception of SAP’s user experience. Fiori has done much for SAP to start that perception change, but I am acutely aware that we are only just beginning on our journey.  I also feel that SAP’s journey is also the same journey that the entire IT industry will need to follow to bring great experiences to our users.

Revisiting the XML Model

Screen Shot 2015-08-01 at 11.56.5030 Days of UI5 - Day 29 by DJ Adams

It’s been more than a couple of years since I first had a look at XML data in the context of UI5. In my “Re-presenting my site with SAPUI5” video I used an XML Model to load the XML feed of my weblog into a UI5 app (gosh, JavaScript views!).

The XML Model mechanism proved very useful this week on a project, and I thought I’d re-examine some of its features. Everyone knows about the JSON and OData Model mechanisms; at least in my UI5 conversations, I don’t hear folks talk about the XML Model much. So I thought I’d give it some love here.

The API reference documentation for the XML Model is a little dry. As Frank Zappa once said, “The computer can’t tell you the emotional story. It can give you the exact mathematical design, but what’s missing is the eyebrows“. We need to look elsewhere for the emotional story, for the eyebrows; and I think a nice place might be the QUnit tests for the XML Model.

Learning from the QUnit sources

Let’s have a look at the source, and see what we can learn. There are actually a couple of QUnit test files; we’ll have a look at just one of them – XMLModel.qunit.html. We’ll just examine the setup and a couple of tests to see what we can find – what we can expect to be able to do with an XML Model. You can explore the rest of the QUnit test files on your own.

At the start of XMLModel.qunit.html, a couple of XML Models are instantiated with some test data as follows:

	var testdata = "<teamMembers>" +
						"<member firstName=\"Andreas\" lastName=\"Klark\"></member>" +
						"<member firstName=\"Peter\" lastName=\"Miller\"></member>" +
						"<member firstName=\"Gina\" lastName=\"Rush\"></member>" +
						"<member firstName=\"Steave\" lastName=\"Ander\"></member>" +
						"<member firstName=\"Michael\" lastName=\"Spring\"></member>" +
						"<member firstName=\"Marc\" lastName=\"Green\"></member>" +
						"<member firstName=\"Frank\" lastName=\"Wallace\"></member>" +
					"</teamMembers>";
	var testdataChild = "<pets>" +
	  		            "<pet type=\"ape\" age=\"1\"></pet>" +
	  		          	"<pet type=\"bird\" age=\"2\"></pet>" +
	  		        	"<pet type=\"cat\" age=\"3\"></pet>" +
	  		      		"<pet type=\"fish\" age=\"4\"></pet>" +
	  		    		"<pet type=\"dog\" age=\"5\"></pet>" +
	  		    	"</pets>";

setXML and setData

The XML data is added to the XML Models with the setXML function:

	var oModel = new sap.ui.model.xml.XMLModel();
	oModel.setXML(testdata);
	sap.ui.getCore().setModel(oModel);

	var oModelChild = new sap.ui.model.xml.XMLModel();
	oModelChild.setXML(testdataChild);

This is different to the setData function, which is also present on the JSON Model, with an equivalent semantic. Here in the XML Model, the setData function would be expecting an XML encoded data object, not a literal string containing XML.

As an example, if we have a variable containing some XML string like this:

xmlstring = "<root><name>DJ</name></root>"

then we could either set it on an XML Model with setXML, like this:

m = new sap.ui.model.xml.XMLModel()
=> sap.ui.d…e.C.e…d.constructor {mEventRegistry: Object, mMessages: Object, id: "id-1438428838337-6", oData: Object, bDestroyed: false…}
m.setXML(xmlstring)
=> undefined
m.getProperty("/name")
=> "DJ"

or with setData, creating an XML encoded data object, like this:

m = new sap.ui.model.xml.XMLModel()
=> sap.ui.d…e.C.e…d.constructor {mEventRegistry: Object, mMessages: Object, id: "id-1438428927599-7", oData: Object, bDestroyed: false…}
m.setData(new DOMParser().parseFromString(xmlstring, "text/xml"))
=> undefined
m.getProperty("/name")
=> "DJ"

A couple of tests

Then we’re off on the tests. There are a couple of tests to check getProperty, the first using a relative context binding:

	test("test model getProperty with context", function(){
		var oContext = oModel.createBindingContext("/member/6");
		var value = oModel.getProperty("@lastName", oContext); // relative path when using context
		equal(value, "Wallace", "model value");
	});


	test("test model getProperty", function(){
		var value = oModel.getProperty("/member/6/@lastName");
		equal(value, "Wallace", "model value");
	});

What we can see here already is that we can access XML attribute values (“lastName” in this case) with the XPath @ accessor. As an aside, the use of the optional second oContext parameter in the getProperty call is something one doesn’t see very much, but is extremely useful.

Element content retrieval

The rest of the file contain a load of other tests, all useful reading material, from the rare-to-see use of the unbindProperty function to aggregation bindings that are comfortable to use.

One thing that we have to wait until test 15 to see is the use of element content:

	test("test XMLModel XML constructor", function(){

		var testModel = new sap.ui.model.xml.XMLModel(

		);
		testModel.setXML("<root>" +
				"<foo>The quick brown fox jumps over the lazy dog.</foo>" +
				"<bar>ABCDEFG</bar>" +
				"<baz>52</baz>" +
			"</root>");
		equal(testModel.getProperty("/foo"), "The quick brown fox jumps over the lazy dog.");
		equal(testModel.getProperty("/bar"), "ABCDEFG");
		equal(testModel.getProperty("/baz"), 52);

	});

Until now we’ve only seen examples of XML where the data is stored in attributes. What about the more classic case of text nodes, like this example XML here?

Well, as we can see, a simple call to getProperty will do what we want. If we’re XPath inclined, we could even add the text() specification like this:

testModel.getProperty("/bar/text()")
=> "ABCDEFG"

and still get what we expect.

Ending where we started

And of course, to round things off, we can always get back to an XML encoded data object with getObject, like this:

testModel.getObject("/bar")
=> <bar>ABCDEFG</bar>

(that result is indeed an object), in a similar way to how we retrieve the whole object from the model:

testModel.getData()
=> #document
   <root>
    <foo>The quick brown fox jumps over the lazy dog.</foo>
    <bar>ABCDEFG</bar>
    <baz>52</baz>
  </root>

The XML Model is a powerful ally, and the QUnit tests are a rich source of information about it. Spend a coffee break looking through the sources, you won’t be disappointed!