ExtJS 4.1 condition in tooltip - extjs4

I'm trying to create a condition inside a tooltip template.
I've declared my template like this:
tooltipTpl: new Ext.XTemplate(
'<tpl for=".">',
'<dl class="eventTip">',
'<tpl if="values.getLength() == 1">',
'<dt class="icon-clock">Time</dt><dd>{[Ext.Date.format(values.start, "d-m")]} - {[Ext.Date.format(Ext.Date.add(values.end,Ext.Date.SECOND,-1), "d-m")]}</dd>',
'</tpl>',
'<tpl if="values.getLength() > 1">',
'<dt class="icon-clock">Day</dt><dd>{[Ext.Date.format(values.start, "d-m")]}</dd>',
'</tpl>',
'<dt class="icon-task">Status</dt><dd>{Name}</dd>',
'</dl>',
'</tpl>'
).compile(),
The idea behind is to be able to display 2 dates (start and end) if event is longer than 1 day, if it is one day event just display that date.
I've declared my model as so:
Ext.define('Urlopy.Model.Plan', {
extend : 'Sch.model.Event',
idProperty : 'id',
resourceIdField : 'userID',
startDateField : 'start',
endDateField : 'end',
fields : [{ name : 'id', type : 'int'},
{ name : 'userID', type : 'string'},
{ name : 'start', type : 'date', dateFormat : 'MS'},
{ name : 'end', type : 'date', dateFormat : 'MS'},
{ name : 'Name'}],
getLength : function() {
return Sch.util.Date.getDurationInDays(this.get('start'), this.get('end'));
}
});
The second line of my tooltip is displayed, but line with dates isn't. It looks like I cant call function from my model in my template.
How to fix this? Is it possible?

The answer to the question - if it is possible to run function from the object passed to the template as a data object, yes. The function will be called.
You can run the following short snippet of code inside the any browser console like FireBug
(of course you need to open the console at the page which has extjs, simple open console on the extjs documentation page) to see it.
Code snippet:
var t = new Ext.XTemplate(
'<tpl for=".">',
'\n===',
'<tpl if="values.getLength() == 1"> ONE </tpl>',
'<tpl if="values.getLength() > 1"> TWO </tpl>',
' *{name}* ',
'===',
'</tpl>'
).compile();
var a = [
{name: 'Foo', getLength: function() {return 1;} },
{name: 'Boo'}
];
var s = t.apply(a);
console.log(s);
You will see the following results:
return 1:
=== ONE *Foo* ===
=== *Boo* ===
return > 1:
=== TWO *Foo* ===
=== *Boo* ===
I don't know the context of using this template with the underlying model, you are not provided code applying the model to the template. But I'm pretty sure that to the template is going the model data but not the whole model object, that is why you can see the second line with modal's field {Name}.
To overcome it you can add to the template its own method, like:
//for the simplicity sake I've not pasted the whole template
//also you can call the *this.getLength(values.start, values.end)*
//and change this method parameters
var tooltipTpl = new Ext.XTemplate(
'<tpl for=".">',
// ...
'<tpl if="this.getLength(values) > 1">',
// ...
'</tpl>',
// ...
'</tpl>'
,{
getLength : function(data) {
//move the model method to the template
return Sch.util.Date.getDurationInDays(data.start, data.end);
}
}).compile();

You can use the model's method..
Define the model static method:
Ext.define('Urlopy.Model.Plan', {
//...
static: {
getLength: function(data) {
console.log('data', data);
console.log(data.start, data.end);
return 5; //just test function
}
}
//.....
});
Use it in the template:
'<tpl if="Urlopy.Model.Plan.getLength(values) == 1">'
So you can delete the template's method.

Related

Xtemplate shows blank item instead of not showing it with sencha touch 2.1

What i want to do is to show the item of a list of data conditionally,that is , when the item meet the condition,it will show,otherwise,it will not show(not means show a blank item).
My data to be showed is like this :
[
{'label':'one','isvisible':'1','value':'one'},
{'label':'two','isvisible':'1','value':''},
{'label':'three','isvisible':'0','value':'three'},
{'label':'four','isvisible':'0','value':''}
]
And my list is like below:
xtype : 'list',
id : 'myListId',
disableSelection : true,
itemTpl : [
'<tpl if="isvisible == 1 && value !=\'\' ">',
'{label}{value}',
'</tpl>'
]
But when the list showed,i have got some blank rows if the item meets the condition(the property 'visible' is 1 or the property 'value' is empty).
At first,i used '<tpl for="." ' ,I followed this link: link but my list of data have no root node,so i used the itemtpl above.
I do not want to modify the strcuture of my list of data,so how can i do ?
UPDATE:
I do not use a store.I just get the data then assign the data to the data config of the list like:
var data=[{text:'1'},{text:'2'},{text:'3'}];//usually the data array comes from the response of an ajax request to the remote server.
var list=Ext.getCmp('myListId');
list.setData(data);
you can filter the store in your controller, before pushing the list view:
store.filter('isvisible', '1');
http://docs.sencha.com/touch/2.2.1/#!/api/Ext.data.Store-method-filter
EDIT:
initialize: function(list) {
var data = [];
Ext.each(list.getData(), function(rec) {
if (rec.data.isvisible == 1) data.push(rec);
});
list.setData(data);
}
Try this
{
xtype : 'list',
disableSelection : true,
itemTpl : [
'<tpl if="isvisible == 1 && value !=\'\' ">',
'{label}{value}',
'</tpl>'
],
listeners : {
initialize: function(list, eOpts ) {
var visibleFilter = new Ext.util.Filter({
property: 'isvisible',
value : 1
});
var valueFilter = new Ext.util.Filter({
filterFn: function(item) {
return item.data.value.length != 0;
}
});
list.getStore().setFilters([visibleFilter,valueFilter]);
}
}
}

sencha touch-2; Store values into HTML

I've a store and model to make AJAX Call and get the result.
Here is my View
Ext.define('kids.view.YouTube', {
extend: 'Ext.Component',
alias: 'widget.YouTubePlayer',
xtype: 'YouTube',
config: {
url: 'http://www.youtube.com/embed/',
videoId: 'qsvpvqvApKo',
vWidth: 420,
vHeight: '315',
styleHtmlContent: true,
aaa: '1',
},
initialize: function() {
var prod = Ext.create('kids.store.vids');
prod.load(function ( ){
prod.each(function (record, id){
tmp = tmp + record.get('vid_url');
});
});
this.callParent(arguments);
var out = Ext.String.format(
[
'<div align="center">',
'<iframe width="{0}" height="{1}" src="{2}"',
'frameborder="0" allowfullscreen></iframe>',
'</div>'
].join(''),
this.getVWidth(),
this.getVHeight(),
**tmp //(the dynamic variable i formed in onLoad event of store**
);
console.log(tmp);
this.setHtml(out);
}
});
I used prod=ext.create('kids.store.vids');
and i'm using onload function, which is fetching values correctly.
how can i use tmp variable out side of onload, becuase the variable is becoming empty. and inside the store.load(function) i can not use this.callParent()
h*ow can i pass dynamic html here, as per the store returned values?*
help me
Pavan
Got it thanks
i've used panel.setHtml to update the html from the variable which i got from store.
thanks

ExtJs 4.1 TreeGrid treecolumn custom renderer

Is it possible to merge 2 columns in TreeGrid, when one of them is xtype 'treecolumn'?
For now I have 2 separate columns, one is standard treecolumn, second is templatecolumn with custom template (basically an image)
What I would like to get should look like this:
So that second column content is added to first but aligned to right.
I have no idea how to even start with that kind of renderer :(
This is code for my columns so far:
{
xtype : 'treecolumn',
text : 'DziaƂ/Pracownik',
width : 200,
sortable : true,
hideable: false,
dataIndex : 'Name',
renderer: function (v, m, r) {
if(r.get('leaf')==true)
m.tdAttr = 'data-qtip="<img src=services/Images.ashx?login='+r.get('login')+' width=60px height=60px>"';
return v;
}
},
{
text : 'Zdj',
width: 40,
align : 'center',
dataIndex : 'Name',
sortable : false,
resizable: false,
xtype : 'templatecolumn',
tpl : imgTpl
},
...
var imgTpl = Ext.create('Ext.XTemplate',
'<tpl for=".">',
'<tpl if="values.leaf == true">',
'<img src="services/Images.ashx?login={login}" width="25px" height="25px"/>',
'</tpl>',
'</tpl>'
);
I will really be gratefully for any hints on how to merge those 2 columns.
Here is what I ended up doing with that:
renderer:function (value, meta, record) {
var tasks = record.get("tasks"),
tpl = this.taskImgTpl,
type, qtip;
if (tasks && tasks.length >0){
Ext.each(tasks, function(task){
if(task.refType) {
type = task.refType;
} else {
type = task.type.name;
}
qtip = Ext.String.format('Status: {0} Assignee: {1} %Complete: {2}',task.state,task.assignee||'',task.pctComplete);
value += tpl.apply([type, qtip]);
},this);
}
return value;
}
And the image template that is being inserted is :
taskImgTpl:new Ext.XTemplate(" <img class='{0} h16' width='16px' data-qtitle='{0}' data-qwidth='120' data-qtip='{1}'/>")
where h16 is a class that gives height:16px, and the dynamically inserted class carries a background image (16x16) of whatever the type of object is being displayed. You of course can just set the src attribute instead.
What I have done is instead using template I've used renderer, so my column now looks like this:
{
xtype : 'treecolumn',
text : 'Employee',
width : 200,
sortable : true,
hideable : false,
dataIndex : 'Name',
renderer : function(v, m, r) {
if (r.get('leaf')) {
return '<div style="float: left">'
+ r.get('Name')
+ '</div><img data-qtip="<img src=services/Images.ashx?login='
+ r.get('login')
+ ' width=60px height=60px/>" src="services/Images.ashx?login='
+ r.get('login')
+ '" width="25px" height="25px" style="float: right; margin-right: 5px"/>';
}
return '<div style="float: left">' + r.get('Name') + '</div>';
}
}
If element is leaf then I display extra image in the right of my column + I've added bigger image after rollover.
To have this working I had to change some css inside ext-all.css:
.x-grid-with-row-lines .x-tree-icon{margin-top:1px; float: left}
.x-grid-with-row-lines .x-tree-elbow,.x-grid-with-row-lines .x-tree-elbow-end,.x-grid-with-row-lines .x-tree-elbow-plus,.x-grid-with-row-lines .x-tree-elbow-end-plus,.x-grid-with-row-lines .x-tree-elbow-empty,.x-grid-with-row-lines .x-tree-elbow-line{height:19px;background-position:0 -1px; float: left}
I had to add float:left to all images that are displayed in that cell:
x-tree-elbow
x-tree-elbow-end
x-tree-elbow-plus
x-tree-icon
I know that this can be optimised a lot, but for me it works fine. If some ExtJS guru could tweak it to work better then you're welcome :)

Sencha Touch 1.1 : How do I get individual list record without tapping on list?

I have a list of items and I have inserted toggle button in my list. Now depending on the value of active in the store I am trying to set the value of toggle button.
The problem I am facing is I don't know how to get list's record without tapping or selecting it.
Here is the code ..
var itemTemplate = new Ext.XTemplate (
'<tpl for = ".">',
'<div>{name}</div>',
'<div class= "subSectionToggleButton"></div>',
'</tpl>'
);
var subSectionList = {
height: 350,
id: 'sList',
xtype: 'list',
store: App.stores.subSections,
grouped: true,
itemTpl: itemTemplate, //Don't need to worry about this
listeners: {
'refresh' : function (e) {
//insert toggle button in empty div class inside template
e.getEl().select('div .subSectionToggleButton').each(function(item) {
var toggleButton = new Ext.form.Toggle ({
renderTo: item,
listeners : {
// After render I want to get the individual record, read whether it is active or not.. and then do setValue(value) on toggle button
'afterrender' : function (f) {
var rec = Ext.getCmp('sList').getRecord(f);
console.log(rec); // I get undefined here
// I know how to get a record when you tap a list item but how do I get without using the tap.
}
}
});
});
}
}
};
It will be best for you to use an if condition in your itemTpl or just get the value decided from a function. So, it will be like this:
var itemTpl = new Ext.XTemplate('<tpl for = ".">',
'<div>{name}</div>',
'<div class= "subSectionToggleButton">{active:this.setToggled}</div>',
'</tpl>',
setToggled : function(active){
if(active == true){ //Check the condition here
return '<div class="active">Active</div>';
}
return '<div class="inactive">Inctive</div>';
}
Or, you can just use a tpl if condition like this:
var itemTpl = new Ext.XTemplate('<tpl for = ".">',
'<div>{name}</div>',
'<tpl if="active==true">', // Or '<tpl if="active==\'true\'">',
'<div class= "subSectionToggleButton">Active</div>',
'</tpl>',
'<tpl if="active==false">',
'<div class= "subSectionToggleButton">Inactive</div>',
'</tpl>',
'</tpl>');
For your given scenario try to pass HTMLElement instead of Ext.Element to getRecord method
var rec = Ext.getCmp('sList').getRecord(f.getEl().dom);
Also you can get access to the list's records through list.store.findRecord
http://docs.sencha.com/touch/1-1/source/Store.html#Ext-data-Store-method-findRecord

Sencha XTemplates issue with call from controller

I am having some difficulty with XTemplates and using the MVC structure. I have went through a few of the tutorials and by themselves they make sense but when I try to apply them to what I am trying to accomplish it does not work that well.
First off, my app consists of TabBarMVC and several views. Some of the views will have 'sub views'. I have the app working from a 'layout' perspective. Tabs are tabbing and views can access subviews. Now the issue is sending data to subviews.
An example is my Bill page to Detail page. In the bill page a user can enter a total and number of people to split the bill against. My controller takes both parameters and divides them and stores them in a 'guests' object. My guests object will be an array of 1-x number of guest objects. (based on the number to split).
I then send that object to an update method in my sub view to update a XTemplate but that is not happening. I can alert the object, and view the data in debugger but I do not know how to update the Xtemplate.
Here is the controller code:
splitdetail: function(options)
{
if ( ! this.splitdetailView)
{
var totalBill = options.data['totalBill'];
var numGuests = options.data['splitBy'];
var totalPerGuest = totalBill / numGuests;
var guestObject = new Array();
var theGuest;
for (var i=0; i<numGuests; i++) {
theGuest = {amount: totalPerGuest}
guestObject.push(theGuest);
}
app.views.calculatorSplitDetail.updateWithRecord(guestObject);
this.splitdetailView = this.render({
xtype: 'CalculatorSplitDetail',
switchAnimation: { type: 'slide'}
});
}
this.application.viewport.setActiveItem(this.splitdetailView, 'slide');
},
and here is my split detail
var guestTemplate = new Ext.XTemplate(
'<tpl for=".">',
'<div class=" x-field guest-amount-row x-field-number x-label-align-left">',
'<div class="x-form-label" style="width: 30%; ">',
'<span>Total bill</span>',
'</div>',
'<div class="x-form-field-container">',
'<input type="number" name="totalGuestAmount" class="x-input-number" value="{amount}">',
'</div>',
'</div>',
'</tpl>'
);
app.views.CalculatorSplitDetail = Ext.extend(Ext.form.FormPanel, {
initComponent: function() {
Ext.apply(this, {
scroll: false,
items: [
guestTemplate,
]
});
app.views.CalculatorSplitDetail.superclass.initComponent.call(this);
},
styleHtmlContent: true,
baseCls: 'calculator-splitdetail-panel',
updateWithRecord: function(record) {
guestTemplate.apply(record);
alert(record[0].amount);
}
});
Ext.reg('CalculatorSplitDetail', app.views.CalculatorSplitDetail);
guestTemplate is just a template, not a control, so it can't refresh itself, but it can generate new html for you. So all you need to do is update your panel with newly generated html:
updateWithRecord: function(record) {
this.update(guestTemplate.apply(record));
alert(record[0].amount);
}