10

I want to do some logic before a view is displayed every time.I cannot go with before rendering method since it is called only once when the view is created and shown for the first-time.Pls help.Any ideas?

Papu
  • 371
  • 4
  • 8
  • 21
  • The current accepted answer misleadingly suggests `onBefore/AfterRendering` as a solution which is an **anti-pattern** in this case (It won't work without calling `invalidate()` every time, plus, `invalidate()` is not even a public method). See [_`onBeforeRendering` is not called every time_](https://stackoverflow.com/q/55082731/5846045). – Boghyon Hoffmann Dec 02 '19 at 11:29

4 Answers4

13

Why do you think the before rendering method of a control is called only once? Do you have any sample code?

I've created a quick a dirty example on jsbin (http://jsbin.com/qikokayo/1/edit?html,output) for you to have a look at. It clearly shows that onInit is called once but onBeforeRendering is called every time...

Also see this snippet from the OpenUI5 SDK which explains:

Lifecycle Hooks

onInit() - Called when a View is instantiated and its controls (if available) are already created. Can be used to modify the View before it is displayed to bind event handlers and do other one-time initialization.

onExit() - Called when the View is destroyed. Use this one to free resources and finalize activities.

onAfterRendering() - Called when the View has been rendered (therefore its HTML is part of the document). Post-rendering manipulations of the HTML can be done here. This hook is the same one that SAPUI5 controls get after being rendered.

onBeforeRendering() - Is invoked before the Controller's View is re-rendered. You would use onInit() in the case that the hook shall be invoked only before the first rendering.

For Controllers without a View, no lifecycle hooks will be called.

Mike
  • 14,010
  • 29
  • 101
  • 161
Jason Scott
  • 643
  • 4
  • 15
  • 3
    Hi, I am using mvc based split app.So when you first add a detail page the before rendering method is called.But when we call the detail page next time by toDetail,then the method is not called.I've tried. – Papu Feb 23 '14 at 10:41
  • 1
    the word "re-rendered" in the onBeforeRendering definition is confusing me...it seems to be invoked before the first rendering of the view as well as upon re-renderings, not only when the view is re-rendered. The jsbin shows onBeforeRendering getting called on first page load: http://jsbin.com/qikokayo/1/edit ... Am I missing something? – Jonathan.Brink Mar 18 '14 at 01:11
  • 1
    _> I've created a quick [example on jsbin](http://jsbin.com/qikokayo/1/edit?html,output) [...] It clearly shows that `onBeforeRendering` is called every time._ .. Of course, you're calling `invalidate()` every time telling the framework to rerender, which isn't a public method btw. Please don't encourage readers to use non-public methods. – Boghyon Hoffmann Jul 02 '19 at 08:17
6

For a modern SAPUI5 fiori-style application involving a Component and associated routing you could always attach a method to your view that would be called whenever there is a match with the supplied route pattern for that view. This route was historically supplied in the metadata of the Component class but since v1.30 it's declared in the manifest.json file.

In the onInit method of your view, you can do:

onInit: function() {
    this._oRouter = this.getOwnerComponent().getRouter();
    this._oRouter.getRoute("yourRouteForThisView").attachPatternMatched(this._onObjectMatched, this);
}

So you have the _onObjectMatched method that would be called every time you are on the view. Here you could place all your code here that should execute before your view is rendered.

_onObjectMatched: function(oEvent) {
    var oArgs = oEvent.getParameter("arguments");
    //If any values were passed in the URL then those will be available in oArgs
    //Do other stuff here
}

You can also use this for your landing page. The first view usually has an empty string "" as its route pattern in the manifest.

Lalit
  • 839
  • 2
  • 14
  • 26
4

Another pattern is as below (with thanks to Matbtt)

onInit : function () {

    //...other code

    var router = this.getOwnerComponent().getRouter();
    var target = router.getTarget("<your route target name>");
    target.attachDisplay(this.onDisplay, this);
},

/** Fires evey time view is displayed.
 *
 * @param oEvent
 */
onDisplay: function(oEvent) {

    console.log('refreshData')
    this._refreshData()
},      

The onDisplay function is fired each time the view is displayed. In my own small experience the on-render events get fired more frequently than one would initially assume.

Vanquished Wombat
  • 9,075
  • 5
  • 28
  • 67
3

I have fixed the issue with onBeforeShow.Thanks jason for your efforts.

Tim Gerlach
  • 3,390
  • 3
  • 20
  • 39
Papu
  • 371
  • 4
  • 8
  • 21
  • I´m using `onBeforeShow` for that case, too. You can see my answer regarding onBeforeShow [here](http://stackoverflow.com/a/25140447/1969374). – Tim Gerlach Aug 19 '14 at 07:18
  • @Papu Please accept this answer to help future readers. The current accepted answer has many flaws (outdated, suggesting to use non-public method, forcing view to rerender) – Boghyon Hoffmann Jul 02 '19 at 09:23