How to switch UI5 content on demand? - sapui5

<semantic:DetailPage title="Detail Page Title">
<mvc:XMLView viewName="query.sap.view.Table" />
<mvc:XMLView viewName="query.sap.view.chart" />
</semantic:DetailPage>
I have two nested views in the same content and I want to display only one of them. When I press a button, it should switch to the other one.

In order to make only one of the controls visible (in our case one of the child Views), one might be tempted to instantiate all controls first and then use the visible property to hide the other "unneeded" controls. But keep in mind that this approach might lead to performance and memory issues depending on the complexity and the number of elements. According to the linked documentation topic:
Don't use visibility for lazy instantiation
When an application has areas that are not visible initially, or if only one of multiple options is visible at a time, do not create all UI controls and set most of them to non-visible! If you do, OpenUI5 will instantiate and initialize all of those controls, which consumes unnecessary time and memory, even when they are not rendered. On top of this, the data binding will also be initialized, which may trigger back-end requests that are not needed at this stage. The impact is particularly big when the parts of the UI that are not visible initially are complex or numerous.
Luckily, UI5 has already built-in lazy loading features..
Switching Views on Demand
Via NavContainer + Router
Configure the targets property inside the app descriptor file (manifest.json) accordingly as shown in: https://embed.plnkr.co/HRSJ44/
For this, we need three properties for the target object of the child view:
parent: Pointing to a parent target name where the parent view is defined
controlId: The ID of the control in which the child view should be attached.
In the Plunker example above, the control is a NavContainer which also offers a sliding animation as a bonus. The animation can be turned off with transition: "show".
controlAggregation: In our case "pages" (default aggregation of NavContainer).
After defining those three properties, we can either display the target view without changing the hash, or navigate to the child view by calling component.getRouter().navTo("thatChildRouteName");. Either way, the child view will be created lazily and we have a flexible way of switching through different child views.
Via "Blocks" (sap.uxap.BlockBase)
Views can be loaded lazily and switched also with sap.uxap.BlockBase See:
Example: https://embed.plnkr.co/9ZVwpP/
Docs:
Creating Blocks
Object Page Blocks
API reference: sap/uxap/BlockBase
Although Blocks are typically used in conjunction with sap.uxap.ObjectPageLayout (OPL), they can be also used independently from the OPL design in freestyle apps.

I suggest adding a single view. Later, on any chosen event, you can use
sap.m.semantic.SemanticPage.removeContent(vContent) to remove the original view and sap.m.semantic.SemanticPage.addContent() to add the new View.
Link to the relevant SAPUI5 Guide Page
Hope it helps you.

Lets have a switch and save its current value to a local JSON Model. Now, we will use this value to switch between the 2 views. If switch is true, show first view else show second switch.
Below is the code:
XML ( I've just used the texts in place of View (same thing)) :
<Switch state='{/showFirstView}' />
<Text text='TExt 1' visible='{/showFirstView}' />
<Text text='TExt 2' visible='{=!${/showFirstView}}' />
Controller:
onInit: function() {
var model = new sap.ui.model.json.JSONModel({showFirstView:true});
this.getView().setModel(model);
},
and it works. Screenshots:
and :

Related

VerticalLayout dynamically hiding visibility

I was wondering whats the best way around dynamically hiding some menu items. At the moment I have 6 items just in a matrix layout row. I want to have 3 items aligned left and 3 items alligned right. If one of the items is set to not visible I want it to move accross. I've done something similiar in a horizontal layout and setting the visibility to hidden. I was wondering if this would work with a vertical layout? Having trouble trying to figure out exactly how I would do it as I'm quite new to UI5 xml css and javscript. Any help would be great.
Also I'm having one other issue unrelated to this, I cant seem to bind my json model to my xml fragment, if I use the same code on my normal xml view it prints out the model data. But on my fragment it just prints it like {person>/fullName} any ideas ?
Belongs to your second question.
Maybe your binding was quoted on copy and paste? Check the native XML Code.
If no data are shown (not "{person>/fullName}"), add dependent to connect the models of your view
var oFragment = sap.ui.xmlfragment(sFragment, "fragmentName", this);
oView.addDependent(oFragment);

A master/slave panel in Extjs 5 MVC

I'm using Extjs5.1 powered by a MVC oriented code style.
I've got a main view which inherits from Ext.panel.Panel with a border layout.
On the east region, there's a grid with a store containing several records (or "models", I don't really know what terminology I should use here). (the "master grid")
On the center region, there is another view that inherits from a Ext.form.Panel and which is supposed to display the selected item of the grid . (the "slave form")
My goal is to refresh the "slave form" with the selected record of the "master grid".
The only way I found to "communicate" between the grid and the form is to execute a fireEvent('selectRecord', ...) from the main view controller and to listen to him inside the form view controller, but it seems odd as the form view is a child item of the main view.
Is there a more common way to do that?
By corrolary, is it a fine practice to make a view call functions of another view directly or should I make only their respective controllers interact?
What I usually do and I believe is the most common approach for this, is having a selectionchange event listener, that updates your form like this:
listeners : {
selectionchange: function(model, records) {
var rec = records[0];
if (rec) {
formpanel.getForm().loadRecord(rec);
}
}
}
for this to work, the name property of your form fields must match the name of the fields in the grid store model.
There is an example of this here: http://dev.sencha.com/extjs/5.1.0/examples/kitchensink/#form-grid

how to hide and unhide authoerable tabs depending upon value selected from a drop down in CQ5

i am trying to create a footer component in CQ5, where i have 4 columns & all are autherable.
But we have to make no of columns autherable too i.e based on a value selected form a dropdown we have to open those many tabs for authoring those many columns only.
i have created a dropdown and have a maximum range of 6 columns. i know that i have to configure a listener for this purpose but don't know how . Requirement is like if i select 3 from the drop down then 3 tabs should come to author 3 columns
pls help me , i am middle of something very important.i need the solution very early too as i have to finish the job as soon as possible
I might be late for this by now but in case you still need it:
You need to add a listener node before closing your drop-down element:
<listeners
jcr:primaryType="nt:unstructured"
loadcontent="function(box){ //here you also need to handle the hide/unhide when the panel loads for the first time. Use this.getValue() to retrive the intial value }"
selectionchanged="function(box, value) {
for(var c=1;c<=value;c++){
this.findParentByType('tabpanel').unhideTabStripItem("tab"+c); // You need to handle the opposite with hideTabStripItem("tab"+c);
}
}"/>
Then on both "loadcontent" and "selectionchange" (these are events on your drop-down) grab the current selected value and use it to hide/unhide the tabs. In this case the tabs would be named "tab1", "tab2", etc, make sure you get the names right.
The ExtJS in the events is finding the "tabpanel" container for the whole dialog, and then hiding/unhiding based on name. You could also set to enable/disable using the methods ".enable()" and ".setDisabled(true)". Just make sure you get the reference to the tab first if you want to do this (something like ".getComponent(tabName).enable()").
I didn't test this specific code, I couldn't find my actual example from my code base but this should take you in the right direction.

Displaying forms using Tree in Qt

I'm building a Qt plugin with multiple forms. I have a main form which has a tree widget placed on the left of the form.
I want to add items to this tree, such that clicking on these items would load the corresponding form on the same form. But I want the tree widget to be active so that I can select any other form also.
I was able to display a form on the main form using the following code:
Form1 *myform;
myform=new Form1(this);
myform->show();
where Form1 is the class of the form i intend to display. However this, covers up the tree widget also. And I have to do a string comparison of the item in tree being clicked to display the appropriate form.
Can someone please help me with this as I'm very new to Qt programming.
Thanks
ixM has a good suggestion. The first step should definitely be to use layouts in your main window - separating the tree from the rest of the window - where you are going to put your form. I would suggest using a splitter, because then the user can resize the two halves. You can set the splitter as the main widget of your CentralWidget in your main window.
QSplitter splitter = new QSplitter(CentralWidget);
splitter->setOrientation(Qt::Horizontal);
splitter->setHandleWidth(3);
splitter->setChildrenCollapsible(false);
MyTree= new QTreeWidget(splitter);
splitter->addWidget(MyTree);
Then add your tree widget to the splitter, which will be on the left side.
The next step is to add a placeholder widget on the right side of your splitter. We are also going to add a layout inside that widget. This layout is very important we are going to use it later.
QWidget WidgetRightSide = new QWidget(splitter);
QVBoxLayout setupLayout= new QVBoxLayout(WidgetRightSide);
setupLayout->setSpacing(0);
setupLayout->setContentsMargins(0, 0, 0, 0);
Now, at this point, this is where my answer really differs from the previous answer. You could use a QStackedWidget. That is certainly an option. The problem with that is that you have to create and load all your forms at the beginning. That uses way more memory, and will take longer to start up. That's not so bad if you have 2-5 forms, but when we are talking about 20, 30 or more forms that's really ugly.
So what I would suggest instead, is that when the user selects something in the tree, we will remove the old form, and add the newly selected form at that point.
When the selected item in the tree changes this is now what we have to do.
First, remove all the stuff from the previously selection form.
QLayoutItem *_Item;
while ((_Item = setupLayout->takeAt(0)))
delete _Item;
Next, figure out what form to show next, and create it.
QWidget *ActiveSetupForm = NULL;
if ( I need to load form 1)
{
ActiveSetupForm = new YourNewForm( WidgetRightSide);
}
else ...
And lastly, add your new form to our layout.
if(ActiveSetupForm)
{
setupLayout->addWidget(pActiveSetupForm);
}
Just as a side note. Layouts are tricky to do by hand. I would strongly suggest that you look into using the QtDesigner when you are creating your forms. It makes life soooo much easier. If you would like to know more about it check out this link.
I don't exactly understand what you are trying to achieve but the bit of code you are showing suggests that you do not use the layouts provided by Qt.
If your goal is to be able to dynamically load a form depending on the item that was clicked in the tree, you could achieve that by having a layout (let's say QHBoxLayout) where you would insert your tree and a QStackedWidget in which you could "store" each form (by using addWidget()) and choose which one you want to display by calling setCurrentIndex().

ui.helper vs ui.item in jQuery UI

I was studying the jQuery UI Sortable widget and it said that all callback functions receive a ui object. Two of its properties are ui.helper nad ui.item. ui.helper is mentioned to be mostly a clone of ui.item, but I can't get the significance of calling it 'helper'. Also, the offset and position properties are defined in terms of the helper and not the item. What's the difference between the two ?
One of the answers mention that the helper fills the void, but the I read in the docs that the helper element is "used for dragging display". What exactly is this helper element and why is it named so?
From what I understand ui.helper is a "clone" of the ui.item. It is cloned so you can edit it with css and make it look like whatever you want it to look like while you are dragging it and it won't effect the original ui.item. So if you had a box and while it was being dragged you wanted it to turn into a blue box with curved edges but only while it was dragging you can by modifying ui.helper.
The helper is the element that fills the void (with visibility: hidden) when the item is dragged.