A master/slave panel in Extjs 5 MVC - forms

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

Related

Persist changes to core data item from SwiftUI view

I'm working on a SwiftUI app that is to display a number of entries from a Core Data database. Basically just about what the XCode template for such apps implements.
I've made two changes:
I put the code for the list item view into a separate file (BookmarkableItemView)
I added a property bookmarked to the item, which I called BookmarkableItem
The code in my view to show the list of items is now:
List(bookmarkableItems) { item in
BookmarkableItemView(item: item)
}
In BookmarkableItemView, the item property is an #ObservedObject.
Now, my BookmarkableItemView also contains a button that should toggle the bookmarked property on the item that the view represents. All fine and well - this is easy. But now I have to persist the changes...
I can think of the following two solutions:
Pass an action (simple a (BookmarkableItem) -> Void) to the BookmarkableItemView that's then called when button in the view is pressed
Have the view itself save the managed object context
The latter is a no-go in my opinion. The first solution works. There's now an bookmarkAction property in the BookmarkableItemView, so the above code looks like that:
List(bookmarkableItems) { item in
BookmarkableItemView(bookmarkAction: { toggleBookmark(item) }, item: item)
}
The action is called by the BookmarkableItemView and as a consequence, the toggleBookmark(_ item:) method is called.
But somehow I feel that I'm missing something about bindings in SwiftUI that would make the process easier? How can I have my parent view get a notification when a sub view performs changes to the data model so I can persist them?
onDisappear check if item.hasChanges
or use onChange on item.hasChanges

Accessing function and model in one controller from another view's controller UI5

I have 2 view A and B with their respective controllers and models defined inside. Due to some reason I have to move 2 elements from A to B view. One of the element is a button link with a press event. I moved the elements to another view but when I click on the link, it does not trigger press. Which I understand is because B 's controller does not have function for that. If I write the same function in B's controller I get an error saying the model's setProperty could not be set as not found. Because that model is in scope in A's controller only. How do I access it?
Press event of link:
pressEvent: function(oEvent) {
this.getModel("stock").setProperty("/Links/Visible", true);
var stockroomsarr = this.getModel("stockRms").getProperty("/Stockrooms");
if (stockrooms !== null && stockrooms.length > 0) {
this.getModel("stock").setProperty("/Text/Visible", false);
}
this.getModel("stock").refresh(false);
},
Regarding your Model: I strongly advice not to have own models for each controllers. Instead you should define and set them in the init of your component.js. They then are accessable in the view controller by calling
this.getOwnerComponent().getModel("urModel")
Another variant would be to create a baseController. In that you can define functions which are to be used by multiple controllers as well as your models. All other controllers extend that baseController, so the models are available in all of them via:
this.getView().getModel("urModel")
Regarding the function you may use the Event Bus. In short it allows you to create events that are triggered in controller A and are listned to in controller B. Read up here for detailed information on how to use it:
https://blogs.sap.com/2015/10/25/openui5-sapui5-communication-between-controllers-using-publish-and-subscribe-from-eventbus/

How to count element of one controller into another

i've a question to ask for my mvc project...
i have two controllers: Giurisprudenza e GiurisprudenzaNode, these controllers implement an index with the list of elements and a crud system to add/edit/remove elements. In the Girusiprudenza view page every element has a button that return you into the relative GiurisprudenzaNode page, with the list of elements contained into the primary element.
I would like to insert a label next to every element of the list in Giurisprudenza that say how many elements there are into that single primary element, but i don't know how to do that count... Anybody can help me?
for this you dont need two controllers or two different view .
For this you need to follow below steps.
Create a viewModel (Customize mix of both models)
add custom property in you this viewmodel for counts
create new view for this ViewModel class .
Let me know if you need code snippet for this.
View Model from MSDN

How to switch UI5 content on demand?

<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 :

Zend frame work multiple view from single action

Can anyone tell me how can i make more then one view through single action.
actually I have a controller action fetching data from model but I have to show data in 2 different views (half data in 1st and rest in 2nd)
I know it is possible.
Can any one explain how it will be implemented.
I'm not entirely sure whether you mean having two different views depending on a condition or two views at the same time.
From the action you can use:
$this->renderScript( 'views/page.phtml' );
and you can use multiple renderScripts and they will stack up and render in the order that they are called. Or you can have a condition separating them.
if($blah)
{
$this->renderScript( 'views/page.phtml' );
return;
}
else
{
$this->renderScript( 'views/page.phtml' );
return;
}
Is this the sort of thing you mean?
Just use the render method of the controller action to display the view you want.
Refer to Rendering Views in the Zend reference manual for more information (you could also use Named Segments if needed/applicable).