Alternate row colours in ExtJS view.View - extjs

I have an ExtJS 4.2 view.View (dataView) using a template, store and model; pretty much as the documentation describes, and the information is displayed fine.
I now need to alternate the background colour of each item. How is this best accomplished?
There aren't any easy config options to do this like Sencha Touch's striped: true, or any inherent styling like in the grid.Panel; I have looked for a listener that would allow for setting the tpl and itemSelector for each item, but there doesn't seem to be anything listed that would suffice.
Code:
Ext.define('productionHistoryModel', {
extend: 'Ext.data.Model',
fields: [ 'Date', 'Fore_Name', 'Event', 'Comments' ]
});
var productionHistoryStore = Ext.create('Ext.data.Store', {
id: 'productionHistoryStore',
storeId: 'productionHistoryStore',
model: 'productionHistoryModel'
});
var historyTpl1 = new Ext.XTemplate(
'<tpl for=".">',
'<div style="margin-bottom: 10px;" class="x-grid-row">',
'<span style="font-weight: bold;">{Date}: {Event} ({Fore_Name})</span>',
'<br/><span>{Comments}</span>',
'</div>',
'</tpl>'
);
var productionHistoryView = Ext.create('Ext.view.View', {
id: 'productionHistoryView',
store: productionHistoryStore,
tpl: historyTpl1,
itemSelector: 'div.x-grid-row',
emptyText: 'No logs available',
disableSelection: true,
autoScroll: true,
maxHeight: 500
});

You're using a view which means you're defining the HTML to be generated yourself, using a XTemplate. That is why there is no built-in feature for striped rows, since the framework simply doesn't know which HTML will be rendered.
The simplest solution is to add a class attribute to each row in your template indicating whether the row number is odd or even, and then use CSS to style the rows accordingly.
Actually there already is an example in the documentation of Ext.XTemplate (scroll down to "Execute arbitrary inline code with special built-in template variables"):
var tpl = new Ext.XTemplate(
'<p>Name: {name}</p>',
'<p>Company: {[values.company.toUpperCase() + ", " + values.title]}</p>',
'<p>Kids: ',
'<tpl for="kids">',
'<div class="{[xindex % 2 === 0 ? "even" : "odd"]}">',
'{name}',
'</div>',
'</tpl></p>'
);
The corresponding CSS code would look like:
.odd {
background-color: white;
}
.even {
background-color: gray;
}

Related

Dynamic enableCellEdit

I am trying to figure out how to dynamically set enableCellEdit on a cell based on information in the row. For example, something like:
$scope.gridOpts = {
data: 'mydata',
columnDefs: [{field: 'sometimesIEdit', enableCellEdit:row.isEditable}]
}
Clearly row is not available in this context. Maybe enableCellEdit is evaluated purely at the column level and not the cell level making what I want to do impossible - I'm not sure.
I know that as a work around I can use editableCellTemplate with ng-if to show plain text, but I would rather the cell never go editable at all.
For me, the only solution that worked is using cellEditableCondition as a function:
cellEditableCondition: function ($scope) { return $scope.row.entity.isEditable }
This is pretty old but figured I'd attempt to answer anyway. I had this exact same problem and solved it using the editableCellTemplate for that column. This is the template I used is something like this:
var editableCellTemplate = '<div class="email" ng-edit-cell-if="isFocused && '
+ 'row.entity.canEdit">'
+ '<input ng-class="\'colt\' + col.index" ng-input="COL_FIELD" '
+ 'ng-model="COL_FIELD" />'
+ '</div>'
+ '<div ng-edit-cell-if="isFocused">'
+ '<div class="ngCellText" ng-class="col.colIndex()"><span ng-cell-text>'
+ '{{COL_FIELD}}</span></div>'
+ '</div>'
+ '</div>';
So only if the row entity has canEdit equal to true can that cell be edited.
Another solution is to decorate one of ng-grid`s directives.
In this case 'ngCellHasFocusDirective'.
The basic logic is preventing event`s from firing if a condition is not met.
Using this method you can control cell edit for a cell when another cell in the row was changed.
I`m note sure if the "CellTemplate" solution will work when another cell in the row is edited and the result of this edit should disable cell editing for another cell in the row.
This is because a cell change activate a $digest on the cell $scope, I dont believe the $digest is fired on the row $scope.
In this gist link below I wrote a decorator for the 'ngCellHasFocus' directive which fires a function defined in "columnDef', the function returns TRUE or FALSE, editable or not.
An exapmle included.
GIST: https://gist.github.com/shlomiassaf/7485c61ecb464f261194
Old question, but as we need to maintain an app still using ng-grid (>=2.0.9), I thought I'd answer.
As it says in the docs (https://github.com/angular-ui/ui-grid/wiki/Defining-columns), you may specify a cellEditableCondition: boolean, either on the columnDef or in the Options object.
It also requires enableCellEdit: 'expression'.
Example is extracted from the link above
$scope.gridOptions = {
data: myDataSource,
enableCellSelection: true,
enableCellEditOnFocus: true,
cellEditableCondition: 'row.entity.editable',
columnDefs: [
{ field: 'firstName', displayName: 'First Name', width: "*", resizable: false, enableCellEdit: false},
{ field: 'lastName', displayName: 'First Name', width: "20%"},
{ field: 'address', displayName: 'Last Name', width: "*" ,
cellEditableCondition: 'row.entity.editable && !row.entity.isAddressDefined()'},
{ field: 'age', cellClass: 'ageCell', headerCellClass: 'ageHeader', width: "**"}]
};

Pass parameters dynamically

I'm trying to retrieve images from database to data view using ExtJS 4. Now I need to pass parameters dynamically. Mostly here..........
Ext.define('${pkgName}.v02x003001.SV02X00300102' , {
extend : 'Ext.view.View',
alias : 'widget.sv02x00300102',
id : 'images-view',
autoScroll : true,
trackOver : true,
multiSelect : true,
height : 310,
overItemCls : 'x-item-over',
itemSelector : 'div.thumb-wrap',
emptyText : 'No images to display',
prepareData : function(data) {
Ext.apply(data, {
shortName : Ext.util.Format.ellipsis(data.name, 15),
sizeString: Ext.util.Format.fileSize(data.size),
dateString: Ext.util.Format.date(data.lastmod, "m/d/Y g:i a")
});
return data;
},
initComponent: function() {
var me = this;
var value= Ext.getCmp('member-sv02x00300104').getValue();
me.store = 'S02X003001',
me.tpl = [
'<tpl for=".">',
'<div class="thumb-wrap" id="{name}">',
'<div class="thumb"><img src="${createLink(mapping:'img', params:[member: **value** , width:100, height:100])}" title="{name}"></div>',
'<span class="x-editable">{shortName}</span></div>',
'</tpl>',
'<div class="x-clear"></div>'
];
me.callParent(arguments);
}
});
So my question is how do I set value into params ( for member field )
createLink is a grails component that is processes server side, before your JS code is run.
You can't pass JS variables to a Java component because Java will always be processed first on the server and then the resulting HTML and JS will be sent to the client for processing. Client will know nothing about your server side code blocks.
I suggest you rewrite createLink piece in HTML and substitute in JS variables like you do with name and short name.

Set a custom value (and fetch it) to every item (XTemplate) of a Ext.view.View

I would like to add a custom value to each item of a Ext.view.View, this is a window name that should be opened when the item will be clicked.
I'm reading the API docs and I found only how to set custom function, is a problem if I set a custom attribute too?
Thanks for any suggestion
What I'm reading: http://docs.sencha.com/ext-js/4-0/#!/api/Ext.XTemplate
Edit 1:
Ext.define('MyApp.view.desktop.Icons', {
extend: 'Ext.view.View',
alias : 'widget.iconsdataview',
tpl: Ext.create('Ext.XTemplate',
'<tpl for=".">',
'<div class="mfo-view">',
'<img src="{image}" alt="{image}" />',
'<p>{title}</p>',
'</div>',
'</tpl>'
),
itemSelector: 'div.mfo-view',
store: 'Icons',
style: 'margin: 2em;',
overItemCls: 'mfo-view-over',
trackOver: true
});
I would like to do something like this:
tpl: Ext.create('Ext.XTemplate',
'<tpl for=".">',
'<div class="mfo-view">',
'<img src="{image}" alt="{image}" />',
'<p>{title}</p>',
'</div>',
'</tpl>',
mycustomproperty: '{property}'
),
and then on itemdblclick event (pseudocode)
itemdblclick(obj, ...) {
openMyWindow(obj.mycustomproperty);
}
Hope this helps
I haven't worked to much in EXTJS 4.o mostly 3.3 but I believe you can do the following:
tpl: Ext.create('Ext.XTemplate',
'<tpl for=".">',
'<div class="mfo-view">',
'<img src="{image}" alt="{image}" />',
'<p>{title}</p>',
'</div>',
'</tpl>',
{ mycustomproperty: '{property}'
}
),
Seems like what I want is not possible because object created by template are htmlelement, and you have to do Ext.get to make them Elements, to actually use them as ExtJS objects.
I solved by accessing the store with the index of itemdblclick method.
Edit 1:
Even better, you can access the item with record parameter, without using index.

extjs adding icons to the titlebar of an extended window widget (two levels of extension)

I am new to extjs....
I am trying to add icons to the title bar of a window.
I am not able to figure out the error in my code
i tried using tools config for the window
Here is my code:
**Ext.ns('DEV');
DEV.ChartWindow = Ext.extend(Ext.ux.DEV.SampleDesktopWidget, {
width:740,
height:480,
iconCls: 'icon-grid',
shim:false,
animCollapse:false,
constrainHeader:true,
layout: 'fit',
initComponent : function() {
this.items = [
new Ext.Panel({
border:true,
html : '<iframe src="" width="100%" height="100%" ></iframe>'
})
];
DEV.ChartWindow.superclass.initComponent.apply(this, arguments);
},
getConfig : function() {
var x = DEV.ChartWindow.superclass.getConfig.apply(this, arguments);
x.xtype = 'DEV Sample Window';
return x;
},
tools: [{
id:'help',
type:'help',
handler: function(){},
qtip:'Help tool'
}]
});
Ext.reg('DEV Sample Window', DEV.ChartWindow);**
SampleDesktopWidget is an extension of Window
Can somebody help me with this
Thanks in advance
I believe title is part of the header. I dont think you can do this with initialConfig programmatically but you can either override part of component lifecycle or hook in with an event. E.g. add this to config. You might (probably) be able to hook in at any early stage after init maybe, but thats an experiment for you.
listeners: {
render: {
fn: function() {
this.header.insert(0,{
xtype: 'panel',
html: '<img src="/img/titleIcon1.gif"/>'
});
}
}
}
However for this particular scenario I would use iconCls
iconCls: 'myCssStyle'
Then include a CSS file with:
.myCssStyle {
padding-left: 25px;
background: url('/ima/titleIcon.gif') no-repeat;
}
This is a good example that might help, using extjs 3.2.1.
Adding tools dynamically

how to apply images to selected items combobox in extjs 4.0

I want to add images in front of the text in an ExtJS combobox. I have the following code in listConfig...
listConfig: {
getInnerTpl: function(displayField) {
var tpl = '<div>' +'my img path is here' + '{name}</div>';
return tpl;
}
},
And my store is like this
Ext.define('state', {
extend: 'Ext.data.Model',
fields: [{ name: 'stateCode', type: 'int' }, { name: 'name', type: "string"}]
});
My JSON response from the server...
[{"stateCode":"0","name":"--Select--"},{"stateCode":"1","name":"ABC"},{"stateCode":"2","name":"XYZ"},{"stateCode":"3","name":"OPQ"},{"stateCode":"188587","name":"LMN"}]
Here i get the image infront of all items in combobox, but I only want the image infront of items with stateCode 1.
Please help
listConfig: {
getInnerTpl: function(displayField) {
var tpl = new XTemplate(
'<div>',
'<tpl if="stateCode > 0">',
'<img src='img/path/image.jpg' />',
'</tpl>',
'</div>'
);
return tpl;
}
}
I know this is old, but since I've encountered similar problem just recently, I'm gonna post my solution, maybe it will be some help to others.
In this case, you can do something like this:
listConfig: {
getInnerTpl: function(displayField) {
var tpl = '<div>' +'{[values.stateCode == 0 ? "<img src=\'path/to/image.jpg\'" : ""]}' + '{name}</div>';
return tpl;
}
},
var tpl = '<div><img src='img/path/image.jpg' class="state-{state}" />{name}</div>';
then uses css clasess to do something with your image (like hide or show)
I'm using ExtJS 5 and this is working for me:
listConfig: {
itemTpl: [
'<tpl if="stateCode = 0"', // If you have to use '<' or '>' you have to encode it (>)
'<img src="path/to/img.png" /> {name}',
'<tpl else>',
'{name}',
'</tpl>'
]
}
None of the answers so far were working for me, except #riza, but that doesn't provide enough logic for what I needed to do with multiple else if statements. It turns out that others were using "," instead of "+" (except #riza) to concatenate the strings of the tpl. Also, #MMZurita makes a good point with the encoding special characters in HTML. So > becomes > and < becomes <. The <div> and </div> need to go at the beginning and end of the actual tpl tag!
listConfig: {
getInnerTpl: function() {
var tpl =
'<div>' +
'<tpl if="id == 1">' +
'<img src="resources/icons/one.png" align="left"> {name}' +
'<tpl elseif="id == 2">' +
'<img src="resources/icons/two.png" align="left"> {name}' +
'<tpl elseif="id > 2">' +
'<img src="resources/icons/Custom.png" align="left"> {name}' +
'<tpl else>' +
'<img src="resources/icons/Standard.png" align="left"> {name}' +
'</tpl>' +
'</div>';
//);
return tpl;
}
}

Resources