(Snapshoots are here for more details)
i got this : a combobox in the main view and 3 tabs that use the combobox to load their store.
The files Mathrice*.js describe the whole view and the others (in directories) are the tabs.
My question is if there is a way to get the combobox in the tabs controller
If your combobox has an ID as displayed below
Ext.create('Ext.form.ComboBox', {
id: 'mycombobox',
renderTo: Ext.getBody()
});
Then you can get the combobox component anywhere in the controller using:
var cb = Ext.getCmp("mycombobox")
//note the name is the id of the combobox
//here cb will be the combobox instance that you need.
Solution :
Just need to to understand how viewModel works in sencha (cf sencha doc)
In tab's controller, i tried to get the parent controller which contains the combobox and then i play like i'm in that view.
Below the controller of one tabs
,mathrice : this.getViewModel().getParent().getView().getController()
,init:function () {
console.log(" VPN Tab Controller");
var me=this
,selectALab = me.mathrice.lookupReference('comboboxLab')
}
If the combo and tabs are under different controllers, there's no need for the tabs controller to be aware of the combo. You want to have the combo's controller fire an event when the combo's change that you are interested in happens. The tabs controller should listen to this event and take action. This approach reduces coupling and makes your app more maintainable.
Related
The case is pretty common, when you dbl click a cell in a grid, modal window with a form appearing, there you make changes, click the Save button, and having the store in a grid updated. In 4-th I did it via loadRecord from grid to form, and then used set-method to apply changes to grid store. Now I'm trying to do it with MVVM approach, and having some stucks. Because when I set the same VM to the grid and form, after form destroying (Save or Cancel button) the VM is also destroying, and the app ruining. And so, we can't use one VM instanse in multiple components. We have to place it in a container, where a grid and a form are. All official examples are of such a type.
And the question is, if anybody resolved this issue?
fiddle
answer from sencha forum
ExtJs 5 ViewModel has nested structure for components, all sub-objects can to use parent's ViewModel. So you could try to add window object to ViewController view:
var form = Ext.create('Plus.view.FormbetV');
var window = Ext.create('Ext.Window', {
frame: true,
width: 350,
height: 200,
modal: true,
layout: 'fit'
});
window.add(form);
this.getView().add(window); // <--- add parent 'scope'
window.show();
And don't forget to remove this code:
//var viewModel = Ext.getCmp('gridbet').getViewModel();
//this.setViewModel(viewModel);
It works for me, but in this case windows size will be limited by grid size.
In addition to user1638582's answer, my own solution was to add selected record to ViewModel of form:
var form = Ext.create('Plus.view.FormbetV',{
viewModel:{
data:{
currentRec:this.getView().getSelectionModel().getSelection()[0]
}
}
});
https://fiddle.sencha.com/#fiddle/jp6
Looking at the examples, the "Data Binding -> Isolated Child Sessions" seems to be what we're looking for:
http://dev.sencha.com/ext/5.1.0/examples/kitchensink/#binding-child-session
Have you read through this blog post, in which an MVVM example for the grid is used?
When we working on a extjs MVC project, we can handle a view event either inside the view or controller. How do we decide what events been handled in the view and what events been handled in the controller. What is the best practice.
For example, I need to pop up a window when a button is clicked. Should the creation of the window goes to controller or resides in the container view object.
One thing you can do is utilize the control() method within your controller definition. For example, take this code,
Ext.define('AM.controller.Users', {
extend: 'Ext.app.Controller',
init: function() {
this.control({
'viewport > panel': {
render: this.onPanelRendered
},
'#editform button[action=save]': {
click: this.onClick
}
});
}
});
This is from the MVC example. You'll notice that it is using the ComponentQuery Language (http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.ComponentQuery) to select a set of Ext objects to assign the render() event. This is saying, for all panels in the viewport, call onPanelRendered() for the render() event. So in your case, you want to select some buttons. So I added another example that selects some form with an id of editform and then select the button that contains the property action = save. You can get very specific with these component queries. I would suggest reading ComponentQuery portion of the API to see further examples. This depends on how you are attempting to select the buttons.
If you are new to MVC maybe you should only listen to events in the controller, once you have developed a couple of projects and you've gained discipline and enjoyed the benefits of listening events in a controller then you would be able to mix it up (when to use a handler and when to use a controller is gonna become obvious).
E.g If you have a FormPanel and you are only gonna listen to a button's click perhaps it doesn't make much sense to create a controller just for that, but in the other hand if you have a grid with a toolbar, action buttons, itemClick's etc then it would be a good idea to have a controller for that view.
The fact that you are using MVC does not mean you are not allowed to use handlers anymore, but do it wisely.
Best regards.
I have a dialog box with a dropdown (name="number", xtype="selection") widget in a tab. While loading the dialog, I need to fetch the value in this dropdown to display/hide another tab.
Both the tabs are in the same dialog (xtype="tabpanel")
I tried adding a ExtJS code as a 'listener' in the 2nd tab (which needs to be hidden/displayed) but it didn't work:
<listeners
jcr:primaryType="nt:unstructured"
render="function() {alert(this.findParentByType('tabpanel').getFieldValues('number')); }"/>
If you take a look at the OOB list component, it has the functionality you are after.
It implements two listeners for a drop-down selection that contains the different choices for which tab to show:
listeners
loadcontent ->
function(){
this.findParentByType('tabpanel').manageTabs(this.getValue(),true);
}
selectionchanged ->
function(box,value){
box.findParentByType('tabpanel').manageTabs(value);
}
Whenever the selection changes it will manage the tab with the selected value, also it will do this when the content
is loaded so you wont have to change the value all the time for the changes to take effect.
You will also see the actual tabs and that they are implementing a listener for rendering:
render ->
function() {
//The different panels will have to have the index corresponsing to their order in the node structure
this.findParentByType('tabpanel').hideTabStripItem( 'the index for the tab' );
}
Finally for this to work, the main tabpanel needs to have the function "manageTabs" defined as a property:
function(tab,noSwitch){
//Here you will have to specify the different node names for the panels
var tabs=['tab1','tab2','tab3',....,'tab n'];
var index=tabs.indexOf(tab);
if(index==-1) return;
for(var i=1;i<tabs.length;i++){
if(index==i){
this.unhideTabStripItem(i);
}else{
this.hideTabStripItem(i);
}
}
this.doLayout();if(!noSwitch)this.activate(index);
}
So this would be possible to just modify a little for your example to work :)
Hope it helps
/Johan
I'm pretty new to Backbone and Marionette and am having a tough time getting my views to communicate.
I've got a composite view that displays a list of items. To add a new item to the list, I have a popup modal that opens in a new item view that is separate from the composite view.
I'm not sure that this is the best way to do this, but in the modal, I created a new instance of the collection with all of the items and added the new item to that collection. This new item shows up in the original composite view, but only after I refresh the page.
I can't seem to figure out how to get the composite view to listen for the add event and render the new model after it is added.
Am I on the right track here? If not, what should I be doing to add to a collection from a modal?
I think I got this figured out. Instead of creating a new collection in the modal view, I passed in the collection from the composite view as a parameter when I created the modal view. Now, when I add a new model in the modal, the 'add' event is automatically triggered on both versions of the collection and the view automatically renders the new model. No need to bind any extra events like I was thinking.
Your solution will work, but means your views are pretty tightly coupled. You might want to look into using events instead (see How do I send a model that was clicked on within a ItemView to another ItemView that is on the same page?)
How your functionality would work with events:
Within the modal, you enter the data for the model to create
When you press the "save" button,
you validate and save the model var myNewModel = ...
you trigger an event: MyApp.MySubApp.trigger("item:add", myNewModel)
In the controllerfor the list view, you listen to that event, and add the new model to the collection.
The handler code in your controller would look something like:
MyApp.MySubApp.on("item:add", function(model){
this.myCollection.add(model);
});
If you'd like to learn more about using events, check out 2 Marionette tutorials I wrote:
http://davidsulc.com/blog/2012/04/15/a-simple-backbone-marionette-tutorial/
http://davidsulc.com/blog/2012/05/06/tutorial-a-full-backbone-marionette-application-part-1/
Both use events to communicate information within the apps.
In addition, basic events are also explained here: http://samples.leanpub.com/marionette-gentle-introduction-sample.pdf
I'm trying to change ComboBox configuration by reinitializing:
Ext.onReady(function(){
var mycb = new Ext.form.ComboBox({
//params
});
//here is other component initizing
var other = ....
onChange: function() {
//here I'm trying to reinitialize ComboBox
mycb = new Ext.form.ComboBox({
// other params
});
}
});
But after onChange event my ComboBox's disapeared. I tried to invoke mycb.destroy() methods, but there's the same result.
Should I unregister or something like that ComboBox? Why my component is disapearing?
use below code ..
mycb.reset();
mycb.removeAll();
// for loading new data
mycb.loadData("new data store");
// to load attributes
mycb.load({params:{start:0, limit:25, reset:true}});
this is working in my code. Please change as per your need.
Probably a better idea would be to remove the original combobox from its container and add a new one in its place. Also perhaps all you need is to reload the store with new data?
Wrap this combo in panel with fit layout. In onChange handler remove combo from that panel, destroy it (combo), and add new combo to the panel. Having additional panel will give you easy way to put it in right place in the layout.