SAPUI5 walkthrough step 4 – XML views, dive in – how does a xml view get created?
Welcome to my SAPUI5 Walkthrough, And Dive In blog series, where I’ll not only walkthrough the tutorial, but dive in, to explore the magic behind SAPUI5. Buckle up and sit tight, it’s gonna be a bumpy ride as I’m no expert in any way shape or form, just a humble learner who loves coding and likes to get to the bottom of things =。=
We’ll continue our journey with step 4 of the walkthrough. The XML view introduced is very simple, which makes a good example for us to take a closer look at how the XML view is created behind the scene 🙂
Here’s our index.html, where we instantiate a XML view with the view configuration object which holds the view name.
Our framework source code treasure hunt starts here.
Which leads us to the factory function of sap.ui.view.
Where it prepares the parameters, moves our configuration object from sId to vView to oView.
It adds a type (XML) to the oView configuration object.
Then, base on the view type, it instantiates a sap.ui.core.mvc.XMLView with the configuration object, and assigns it to our view object.
If we step into it, we’ll be taken to the constructor method of the Control class, you may wonder what XMLView has anything to do with Control, turns out XMLView was extended from Control, well, not exactly, before we dive into the source code, let’s take a high-level look at the inheritance chain of the classes we’ll about to get into:
sap.ui.core.Control (base class for Controls, creates and initializes a new control with the given sId and settings)
sap.ui.core.Element (base class for UI elements, constructs and initializes an UI Element with the given sId and settings)
sap.ui.base.ManagedObject (base class that introduces some basic concepts like state management or data binding)
sap.ui.base.EventProvider (provides internal eventing facilities for objects)
sap.ui.base.Object (base class for all SAPUI5 Objects)
Alright, with this information in mind, let’s continue with our source code debugging, Control’s constructor calls Element’s constructor with the configuration object as the argument. (from this point onwards, you’ll probably find a lot of similarity between the following content and second part of my last blog – how does a control get created, well, view and control they are all came from the same chain after all. I do think I explain things better this time around : )
Element’s constructor calls ManagedObject’s constructor.
ManagedObject’s constructor calls EventProvider’s constructor.
EventProvider’s constructor calls BaseObject’s constructor.
BaseObject’s constructor, end of the chain, it throws error if the view we’re creating is not a instance of the BaseObject, other than that, it does not do anything else.
After that, we get pop back to the EventProvider’s constructor, it creates the mEventRegistry map and sets it to an empty object.
Then, we’re taken another stack back, to the ManagedObject’s constructor, where quite a few things happen. First, it shifts the sId (configuration object) to mSettings, and sets our view’s sId to null since there’s no sId given explicitly.
Then it generates a sId for the view object.
It creates a bunch of properties and sets them with default values, we see a lot of familiar faces here, like the properties map, aggregations map, model object, binding related properties, turns out this is where they were born 🙂
Then it registers the object in the Core.
By calling the registerElement method.
Which essentially adds our view object to the global mElements map.
After the registration, it calls InitCompositeSupport, which initializes the view and connects it to the controller.
There’s 4 method / function calls within InitCompositeSupport, we’ll focus on the first 2 calls (the last 2 does not really do anything in our case).
Instead of showing screenshot after screenshot, which will most likely get people confused, I’ll try to explain what the first 2 calls in below format, hopefully the hierarchy layout plus my super expressive argument names plus right amount of comments could make things easier 🙂
initViewSettings(mSettingsAKAconfigurationObject) |—> jQuery.sap.loadResource(“App.view.xml”).documentElement // to loads in our xml document then sets its content to xmlContent |—> fnProcessView |—> XMLTemplateProcessor.parseViewAttributes(xmlContent, viewObject, mSettings) // to parse only the attributes of the XML root node fnInitController() |—> createAndConnectController(viewObject, mSettings) // which does nothings in our case |—> onControllerConnected(oControllerWhichDoesNotExistInOurCase) |—> ManagedObject.runWithPreprocessors() |—> XMLTemplateProcessor.parseTemplate(xmlContent, viewObject) // to parse a complete XML template definition the full node hierarchy, it returns an array containing Controls and/or plain HTML element strings |—> parseChildren(xmlNode) |—> parseNode(childNode) |—> createControlOrExtension(childNode) |—> createRegularControls(childNode) // to create a plain and simple regular UI5 control |—> handleChildren(childNode, oDefaultAggregation, mAllAggregations) // there’s no children to be handled in our case |—> createControls(node) |—> createControlOrExtension(node) // recursive call, it gets in a loop to have all UI5 controls required for the application created out of children nodes and their aggregations |—> oView.addAggregation("content”, oChildControlJustCreatedAndReturned)
Now, we’re back. Then we continue with runPreprocessor (there’s no preprocessor registered in our case).
It calls fireAfterInit, which does not do anything neither in our case, this is the end of InitCompositeSupport.
After InitCompositeSupport, the init method will be called if it exists which is not in our case, then, it applies settings, sets all properties, aggregations, associations and event handlers as given in.
It only does one thing in our case, which is to set the viewName property.
In the end, it returns the view object.
And lastly, it places it at HTML document body.
The End 😀
With our findings above, we now know how the control object was created out of xml, but something seems missing between the control object and what we see on the web page, hmm…right, HTML, thanks to Mr. Sankara Rao Bhatta’s question, let’s continue our journey, to find out how does the control object get turn into HTML.
It’s actually simpler than you may think, allow me to dive into it with a new example.
Here we have an UI5 button control. (not sure if my post had reached the limit of images can be inserted, I’m not able to insert any new images…I’ll upload the images onto my dropbox, and insert the public links here, please let me know if you can not see them).
Here’s its underlying HTML we see in the Chrome elements tab. Which part of the UI5 framework code is responsible for creating these HTML markups?
And…here’s the ‘man’ of the hour, the renderControl method.
Once we get the right renderer object, the render method will be invoked upon it.
Within the render method, things are pretty straight forward.
And here’s the end of the HTML button element markup.
THE END 😀