Marionette Composite Item View Capture - backbone.js

I have a composite view which consist of item view. I need to capture the events of item view, what I am trying to capture is specific item view capture as I am rendering a pop up modal on click of button in item view. The Modal needs to contains the details of item for which it is clicked. Whats happening is if I put the event capture in either or item or composite view with query selector of buttons (this button has hidden span of item id) it always selects the first items.
Sounds like it is doing right thing as the item view repetition in composite view is not changing the id of buttons (even if the hidden span has different id).
Quesiton is how do I achieve capturing specific item events with attributes captures.
code below :
ItemView:
var regItemView = Marionette.ItemView.extend({
template: ProgramRegistraionMainItemView,
tagName: 'div',
className : 'accordion_in',
events : {
'click #subbtn' : function () {
var prgid = $('#regid').html();
var rate = $('#rate').html(); MyApp.mainregion.currentView.appcontent.currentView.maincontent.currentView.contentregion1.currentView.prgregmainmodal.show(new ProgramRegistrationModalView({selectedprgid : prgid,rate: rate}));
}
}
});
Composite View
var RegistrationView = Marionette.CompositeView.extend({
itemView : regItemView,
itemViewContainer: "#mainaccordion",
template : ProgramRegistraionMainCollectionView,
initialize : function(programcollection)
{
this.collection = programcollection;
this.model =null;
},
model : this.model,
collection : this.collection,
showAccord : function () {
//console.log("In Accodian show"+$("#mainaccordion").html());
$("#mainaccordion").smk_Accordion({
showIcon: true, // Show the expand/collapse icons.
animation: true, // Expand/collapse sections with slide aniamtion.
closeAble: true, // Closeable section.
slideSpeed: 200, // the speed of slide animation.
closeOther : false
});
}
Aim is to get the program id of the clicked item (rendered through item view).

From your regItemView's event hash, it looks like the issue is with using an html id for the jQuery event handler. id's are supposed to be unique across the whole page but you have repeated it for each ItemView. Change it to a class or an element name (if you've only got one per item view):
var regItemView = Marionette.ItemView.extend({
template: ProgramRegistraionMainItemView,
tagName: 'div',
className : 'accordion_in',
events : {
'click button' : 'showModal'
},
showModal: function () {
// Show modal somehow
// you can access the model in here as this.model
}
});
Marionette sets the event handler context as the item view so you can simple access the model as this.model. This is better than adding data-id tags into your HTML to retrieve the model.

Related

Programmatically selecting grid row does not fire itemclick event in ExtJS4

I am building an ExtJS4 Web Application and I have a "page" where I have a Grid whose records come from a database. After loading the store of the grid, I want the first item to be selected.
This is what I've tried so far:
store.load({
callback: function() {
if(store.count() > 0){
grid.getSelectionModel().select(0);
//grid.getView().select(0);
}
}
});
The store loads the database records properly as they're shown in my grid. The first row is also highlighted as if it was clicked. However, my listener/controller for the itemclick event isn't firing as opposed to when I manually click the row.
I've also tried grid.getView().select(0); as well as grid.getSelectionModel().selectFirstRow(); but apparently, both those aren't functions.
My grid row appears to be selected by the itemclick function isn't being called at all.
You should use 'selectionchange' listener in 'Ext.selection.Model' instead of 'itemclick' in grid class. This listener will be fired in both cases when rows are clicked in grid and rows are selected programmatically.
Probably the code will be like this:
Ext.create('Ext.grid.Panel', {
selModel: Ext.create('Ext.selection.Model', {
...
listeners: {
selectionchange: function( this, selected, eOpts ) {
// Write your listener here or fire another event in view controller
}
}
}
store: ...
});

Sending values from a view to another using EXTJS

Im' using EXT 4.2.0.
I have 2 views : view 1 and view 2.
In view 1 i have a Ext.grid.Panel which (in his associated controller) contains a selectionchange event lisetner .
After selectionchange is triggred, i go the the view 2 in which i have a form.
My need is to have control on the from of the view 2 from view 1.
I mean by control sending values, disabling buttons ...
For information, concerning sending values issue, i'v already tried
Ext.getCmp('view2ID').getForm().loadRecord(this.getMyVar());
But this seems not to be working and i don't know why !
Could you help me please ? :)
Option 1 : As said by #Lorenz,call the method in your controller
selectionchange:function( record, selected, eOpts ){
//getController
controller = globalVar.getController('Controller');
controller.onSelectionChangeEvent(record);
}
Option2 : You can pass config object to the View2 when creating a instance
In view1,mention config property;
//View 1....
config :{
recordObj : ''
},
.........
selectionchange:function( record, selected, eOpts ){
var form = Ext.create('My.view.Form',{recordObj :record});
}
............
//Your View2 might be like
Ext.define('My.view.Form', {
extend : 'Ext.form.Panel',
config :{
recordObj : ''
},
initComponent : function() {
var record = this.getRecordObj();
this.items = [
];
this.callParent();
//Set form values
this.getForm().setValues(record);
}
});
The problem was quiet difficult : Actions sent from View1 were executed befaure view 2 is rendred ! Even if my code was some think like this :
ControllerOfView1
{
CodeToLoadView2;
InstructionsToControlView2;
}
The solution was to add a listeners on my View2 and parametrize afterrender.
So the code hase become :
afterrender: function() {
this.loadRecord(this.getMyVar2());
}
You can use the custom fire event , in that you can send the data you want and the component reference.
app.fireEvent('selectionChanged',view1.grid);
you need the listen for the selectionChanged in the view2.
something like
app.on("selectionChanged",onSelectionChanged)
onSelectionChanged : function(grid){
console.log(grid);
}

Extjs grid column header, add dropdown menu item to specific columns

I'm trying to add a button to the column header drop-down menus in my grid. However, I only want to add it to columns with certain itemId. So far I've got it working to add the button to all columns, see code below. I dont see where I could check each column's itemId though, it doesn't seem to iterate through the columns. Is there any workaround for this? Thank you!
items:[{
region:'center',
xtype:'grid',
columns:{
items: COLUMNS, //defined in index.php
},
store:'Items',
selType: 'checkboxmodel',
listeners: {
afterrender: function() {
var menu = Ext.ComponentQuery.query('grid')[0].headerCt.getMenu();
menu.add([{
text: 'edit',
handler: function() {
console.log("clicked button");
}
}]);
}
}
}],
The grid column menu exists in one instance which is shared for all columns. Because of this you can not add menu item only for one column.
However you can show/hide menu item in this menu for specific column. You can use menu beforeshow event and get information about column from menu.activeHeader property:
listeners: {
afterrender: function(c) {
var menu = c.headerCt.getMenu();
// add menu item into the menu and store its reference
var menuItem = menu.add({
text: 'edit',
handler: function() {
console.log("clicked button");
}
});
// add listener for beforeshow menu event
menu.on('beforeshow', function() {
// get data index of column for which menu will be displayed
var currentDataIndex = menu.activeHeader.dataIndex;
// show/hide menu item in the menu
if (currentDataIndex === 'name') {
menuItem.show();
} else {
menuItem.hide();
}
});
}
}
Fiddle with live example: https://fiddle.sencha.com/#fiddle/3fm

How to select a form element based on the value from a field in backbone.js

I have a dynamic form where I am starting with a drop-down field with two values: bar chart and trend chart. If bar chart is selected I want to show a multi-select drop-down box for the dimension values while if trend chart is selected I want to show a single-select drop-down box.
With the template and model shown below, the multi-select box is only shown after the module is saved the first time. How can I get the isBarChart variable to be set so I can use it to determine if the select box shown should be multi-select or single-select before the module has been saved.
Thanks.
From the template:
%div.select_module_type
Module type:
%select{ :class => "module_type" }
{{#select module_type}}
%option{ :value => '' }
%option{ :value => 'bar_chart' } Bar chart
%option{ :value => 'trend_chart' } Trend chart
{{/select}}
%div.select_dimension_value
Dimension value:
{{#if isBarChart}}
%select.dimension_value{ 'multiple' => true }
{{#select dimension_value}}
{{/select}}
{{else}}
%select.dimension_value
{{#select dimension_value}}
{{/select}}
{{/if}}
From the model:
isBarChart: ->
return #get('module_type') == 'bar_chart'
From the view:
showDimensionValuesSelector: (e) ->
$(#el).find('div.select_dimension_value').hide()
$(#el).find('div.date').hide()
this_selector = $(#el).find('select.module_type')
table = $(#el).find('select.table').val()
return true if table == ''
dimension_selector = $(#el).find('select.dimension[data-table="'+table+'"]')
dimension = dimension_selector.val()
return true if dimension == ''
$(#el).find('div.select_dimension_value .preloader').css('display', 'inline')
$(#el).find('select.dimension_value').hide()
$(#el).find('select.dimension_value').html('')
$(#el).find('div.select_dimension_value').show()
$(#el).find('div.date[data-table="'+table+'"]').show()
self = #
$.get(
'/dashboards/'+#model.get('dashboard_id')+'/dashboard_modules/dimension_values',
{ table: table, dimension: dimension },
(data, status, xhr) ->
_.each(data, (item) ->
if item.value != null and self.model.has('dimension_value') and item.value.toString() == self.model.get('dimension_value').toString()
selected = 'selected="selected" '
else
selected = ''
$(self.el).find('select.dimension_value').append('<option '+selected+'value="'+item.value+'">'+item.name+'</option>')
)
$(self.el).find('select.dimension_value').prepend('<option value=""></option>')
$(self.el).find('select.dimension_value').show()
$(self.el).find('div.select_dimension_value .preloader').hide()
,
'json'
)
since you have a model already, you can just set the value on the model without saving it to the server:
in your view:
events: {
'change .module_type': handleModuleTypeChange
},
handleModuleTypeChange: function() {
this.model.set({
module_type: this.$el.find('.module_type').val()
});
}
then listen to your model changes, rerender the template:
//view initialize
initialize: function () {
this.listenTo(this.model, 'change', this.render);
}
I'm not sure why the select has to be rendered after the model is saved...if that's the case, you may wanna move the Dimensions part into new views.
==============================================================
EDIT: (Dec/01/2013)
A simple jsfiddle: http://jsfiddle.net/8x7rU/
this is a simple example of DOM events changing the model, and then the model changes trigger view rendering.
in this case the whole view is rerendered when the model attribute 'module_type' is changed. And, by changing the Module Type dropdown, the view is setting new 'module_type' values on the model.
lots of the DOM related logic is actually in the template, when the view rerenders, the template knows the current state of the model then render accordingly.

Drag and Drop stops working for an item which is once dragged

I have an ExtJS treepanel in Container A on page and there's another Container B.
The treepanel is initialized with items via Ajax call. In the viewConfig of treepanel, I've added itemadd event listener, in which I register added items as DragSource. Following is the itemadd event listener within viewConfig of treepanel.
'itemadd': function(records, node){
// Iterate over each child record of parent node in treepanel.
Ext.each(records, function(record){
var dragSource,
field,
fieldId;
field = Ext.query('[id='+record.data.listId+']')[0]; // I've manually added 'listId' which has unique value gained from Ext.id() for each record item.
fieldId = field.id;
dragSource = new Ext.dd.DragSource(field, {
isTarget : false
});
dragSource.dragData = {
record: record
};
});
}
And in the items of Container B, I have added a View named MyView which extends Ext.container.Container internally. So in the afterrender of Container B, I'm registering itself as a DropTarget. Here's how I do that;
'afterrender': function(containerMain) {
var dropZone,
myView = Ext.ComponentQuery.query("myview")[0];
dropZone = new Ext.dd.DropTarget(containerMain.getEl()); // Register Container B as DropTarget.
dropZone.notifyDrop = function(source, event, params) {
myView.doSomething(params.record); // This method will handle data of dropped record and internally show something on UI.
};
}
Now the here's problem described in step-by-step usage.
I drag an item from treepanel into Container B for first time and it works fine as intended.
I don't allow to add duplicate items again into MyView, I have a Remove button for each item added to remove it from MyView.
I remove the item which I added.
I try to drag it again from treepanel but it is no longer a draggable item.
Though I can still drag another item from same treepanel and add it, but not the first one which I added and removed earlier (and same thing would happen for all items which I once add to MyView. Note that removing of item is not necessary to reproduce the issue, only adding it causes this.
So what is getting wrong here?
Any help would be great.
I suggest to use the Ext.tree.plugin.TreeViewDragDropView (ptype: treeviewdragdrop) plugin for the tree instead of handling it manually.
Example for the treepanel:
var treePanel = Ext.create('Ext.tree.Panel', {
(...),
viewConfig: {
plugins: {
ptype: 'treeviewdragdrop',
ddGroup: "sameGroup",
enableDrop: false
}
}
});
For the panel:
var panel = Ext.create('Ext.panel.Panel', {
(...),
listeners: {
'afterrender': function(component) {
var dropZone = Ext.create('Ext.dd.DropTarget', component.body.dom, {
ddGroup: 'sameGroup',
notifyDrop: function(source, event, params) {
var myView = panel.up('myview');
myView.doSomething(source, event, params);
return true;
}
});
}
}
});

Resources