In an ExtJS grid I have a column in which when the content of a cell is a certain value, a button should be displayed.
I define the column which will contain the button like this, which calls a rendering function:
{
header: 'Payment Type',
width: 120,
sortable: true,
renderer: renderPaymentType,
dataIndex: 'paymentType'
}]
in the rendering function, I return either text or the button itself:
function renderPaymentType(val) {
if(val!='creditInform') {
return val;
} else {
return new Ext.Button({
text: val,
width: 50,
handler: function() {
alert('pressed');
}
});
}
}
This basically works, except that the button is displayed as the text [object Object]:
What do I have to do so that the button is displayed as a button instead of as text?
Addendum
adding .getEl():
function renderPaymentType(val) {
if(val!='creditInform') {
return val;
} else {
return new Ext.Button({
text: val,
width: 50,
handler: function() {
alert('pressed');
}
}).getEl();
}
}
produces a blank:
adding .getEl().parentNode.innerHTML:
function renderPaymentType(val) {
if(val!='creditInform') {
return val;
} else {
return new Ext.Button({
text: val,
width: 50,
handler: function() {
alert('pressed');
}
}).getEl().parentNode.innerHTML;
}
}
causes some kind of rendering problem with the rest of the code altough in Firebug I strangely don't get any errors:
Try
return new Ext.Button({
text: val,
width: 50,
handler: function() {
alert('pressed');
}
}).getEl();
Your returning a JavaScript object to your renderer rather then a dom node. If doesn't work then your renderer expects a HTML string so you can try
Ext.Button({ ... }).getEl().parentNode.innerHTML
Either should solve your problem.
This worked for me:
renderer: function (v, m, r) {
var id = Ext.id();
Ext.defer(function () {
Ext.widget('button', {
renderTo: id,
text: 'Edit: ' + r.get('name'),
width: 75,
handler: function () { Ext.Msg.alert('Info', r.get('name')) }
});
}, 50);
console.log(Ext.String.format('<div id="{0}"></div>', id));
return Ext.String.format('<div id="{0}"></div>', id);
}
Ref: http://ext4all.com/post/how-add-dynamic-button-in-grid-panel-column-using-renderer
When ever you see syntax of that nature, chances are you're looking at the output of the toString method on an object.
Which means you're displaying the object, and not a result.
console.log({
toString:function(){
return 'toString method.'
};
});
console.log(new Object())
Object.prototype.toString = function(){
return 'All object to string methods are now overriden.';
}
console.log(new Object());
the API documentation says this
renderer : Mixed For an alternative to
specifying a renderer see xtype
Optional. A renderer is an
'interceptor' method which can be used
transform data (value, appearance,
etc.) before it is rendered). This may
be specified in either of three ways:
A renderer function used to return
HTML markup for a cell given the
cell's data value.
A string which
references a property name of the
Ext.util.Format class which provides a
renderer function.
An object
specifying both the renderer function,
and its execution scope (this
reference) e.g.:
{
fn: this.gridRenderer,
scope: this
}
You're using the renderer function option, which means your function needs to return a html markup string, rather than a new Button object. To show a button, you might need to use the column's editor property
Related
Once a grid is rendered how can I set focus to the first item. I am running into a problem where when the grid is updated (collection changes) then focus is lost for the entire application .
I am using the moonstone library.
{
kind: "ameba.DataGridList", name: "gridList", fit: true, spacing: 20, minWidth: 300, minHeight: 270, spotlight : 'container',
scrollerOptions:
{
kind: "moon.Scroller", vertical:"scroll", horizontal: "hidden", spotlightPagingControls: true
},
components: [
{kind : "custom.GridItemControl", spotlight: true}
]
}
hightlight() is a private method for Spotlight which only adds the spotlight class but does not do the rest of the Spotlight plumbing. spot() is the method you should be using which calls highlight() internally.
#ruben-ray-vreeken is correct that DataList defers rendering. The easiest way to spot the first control is to set initialFocusIndex provided by moon.DataListSpotlightSupport.
http://jsfiddle.net/dcw7rr7r/1/
enyo.kind({
name: 'ex.App',
classes: 'moon',
bindings: [
{from: ".collection", to: ".$.gridList.collection"}
],
components: [
{name: 'gridList', kind:"moon.DataGridList", classes: 'enyo-fit', initialFocusIndex: 0, components: [
{kind:"moon.CheckboxItem", bindings: [
{from:".model.text", to:".content"},
{from:".model.selected", to: ".checked", oneWay: false}
]}
]}
],
create: enyo.inherit(function (sup) {
return function () {
sup.apply(this, arguments);
// here, at least, the app starts in pointer mode so spotting the first control
// isn't apparent (though it would resume from that control upon 5-way action).
// Turning off pointer mode does the trick.
enyo.Spotlight.setPointerMode(false);
this.set("collection", new enyo.Collection(this.generateRecords()));
};
}),
generateRecords: function () {
var records = [],
idx = this.modelIndex || 0;
for (; records.length < 20; ++idx) {
var title = (idx % 8 === 0) ? " with long title" : "";
var subTitle = (idx % 8 === 0) ? "Lorem ipsum dolor sit amet" : "Subtitle";
records.push({
selected: false,
text: "Item " + idx + title,
subText: subTitle,
url: "http://placehold.it/300x300/" + Math.floor(Math.random()*0x1000000).toString(16) + "/ffffff&text=Image " + idx
});
}
// update our internal index so it will always generate unique values
this.modelIndex = idx;
return records;
},
});
new ex.App().renderInto(document.body);
Just guessing here as I don't use Moonstone, but the plain enyo.Datalist doesn't actually render its list content when the render method is called. Instead the actual rendering task is deferred and executed at a later point by the gridList's delegate.
You might want to dive into the code of the gridList's delegate and check out how it works. You could probably create a custom delegate (by extending the original) and highlight the first child in the reset and/or refresh methods:
enyo.Spotlight.highlight(this.$.gridList.childForIndex(0));
Ruben's answer adds on to my answer that I posted in the Enyo forums, which I'm including here for the sake of completeness:
Try using
enyo.Spotlight.highlight(this.$.gridList.childForIndex(0));
I added a rendered() function to the Moonstone DataGridList sample in the Sampler and I found that this works:
rendered: function() {
this.inherited(arguments);
this.startJob("waitforit", function() {
enyo.Spotlight.highlight(this.$.gridList.childForIndex(0));
}, 400);
},
It didn't work without the delay.
I'm slowly trying to slug my way through learning OOJS by building an accordion toggle and I'm having a hard time.
EDIT: Slowly getting there. I've got the toggle functioning how I want to. Unfortunately I'm calling the add / remove class incorrectly(?).
I'm currently calling it like:
accordion.ELEMENTS.TRIGGER.click(function() {
if ($(this).parent().hasClass(accordion.CLASSES.OPEN)){
$(this).parent().removeClass('open')
}
else {
$(this).parent().addClass('open');
}
});
And I would rather call it via the EVENTS.OPEN & EVENTS.CLOSE or even throw both of this into the EVENTS.BIND and have BIND sort out whether or not if it is open or not :
Here's a JSFiddle, I'm trying to bind the EVENTS.OPEN and EVENTS.CLOSE instead of trying to find the parents.
var accordion = {
ELEMENTS: {
HOME: $('.js-accordion-toggle'),
TRIGGER: $('.js-accordion-trigger'),
PANEL: $('.js-accordion-panel')
},
CLASSES: {
OPEN: 'open'
},
EVENTS: {
OPEN: function() {
if (ELEMENTS.HOME.hasClass(accordion.CLASSES.OPEN)) {
console.log(this + "open");
ELEMENTS.HOME.addClass(accordion.CLASSES.OPEN);
}
else {
console.log("this should close");
this.close();
}
},
CLOSE: function() {
accordion.ELEMENTS.HOME.removeClass(accordion.CLASSES.OPEN);
},
//BIND: function() {
// accordion.ELEMENTS.HOME.each(function() {
// accordion.EVENTS.OPEN();
// });
//}
},
fn: {
attachEvents: function() {
accordion.ELEMENTS.TRIGGER.click(function() {
console.log(this);
if ($(this).parent().hasClass(accordion.CLASSES.OPEN)){
$(this).parent().removeClass('open')
}
else {
$(this).parent().addClass('open');
}
});
}
},
init: function() {
accordion.fn.attachEvents();
}
}
accordion.init();
I managed to get your original fiddle to work by invoking accordion.init() after your object definition. I also had to replace your line 37 with accordion.ELEMENTS.PANEL.addClass(accordion.CLASSES.OPEN); to get rid of some undefined object error.
As for your new codes, you can simplify your codes by removing the if..else statement in line 19 and 22 with jQuery.toggleClass, to make it looks like:
$(this).closest(toggleHome).toggleClass(toggleClass);
what i am trying to do is dynamically generate WordPress tinymcs listbox values. but it seems my getValue function is not working well or its not possible to add getvalue() function to value parameter. this code is not working. please tell me how to do this. i need this for my new plugin development. sorry for bad english :(
here i have posted the code bellow
(function() {
tinymce.PluginManager.add('AP_tc_button', function( editor, url ) {
editor.addButton( 'AP_tc_button', {
text: 'My test button',
icon: 'wp_code',
onclick: function() {
editor.windowManager.open( {
title: 'Select Your AD',
body: [
{
type: 'listbox',
name: 'level',
label: 'Header level',
values: getValues()
}],
onsubmit: function( e ) {
editor.insertContent('dd');
}
});
}
});
});
})();
function getValues() {
//Set new values to myKeyValueList
tinyMCE.activeEditor.settings.myKeyValueList = [{text: 'newtext', value: 'newvalue'}];
return editor.settings.myKeyValueList;
}
Try changing return statement to
return tinyMCE.activeEditor.settings.myKeyValueList;
variable editor is probably undefined in global scope.
I am using the RowExpander to display additional information about each row in a grid. Some of the rows do not have any additional information. For those rows, How can I get the expand icon (plus sign) to not be rendered? Is there a function that can be used like a filter?
I have seen a similar question on here that says there is a function called renderer(), but I tried that and it does not get called.
I came up with a solution to the problem. I extended the RowExpander pluging and copy and pasted the getHeaderConfig function into my new plugin. This allowed me to make the necessary changes to the renderer function to check if each record has anything to display in the rowBody/rowExpander
Ext.define('MyApp.plugins.RowExpander', {
extend: 'Ext.grid.plugin.RowExpander',
alias: 'plugin.rowexpanderplus',
getHeaderConfig: function () {
var me = this;
return {
width: 24,
lockable: false,
sortable: false,
resizable: false,
draggable: false,
hideable: false,
menuDisabled: true,
tdCls: Ext.baseCSSPrefix + 'grid-cell-special',
innerCls: Ext.baseCSSPrefix + 'grid-cell-inner-row-expander',
renderer: function (value, metadata, record, a, b, store, grid) {
if (record.data.notes.length === 0) {
return '<div></div>';
}
// Only has to span 2 rows if it is not in a lockable grid.
if (!me.grid.ownerLockable) {
metadata.tdAttr += ' rowspan="2"';
}
return '<div class="' + Ext.baseCSSPrefix + 'grid-row-expander" role="presentation"></div>';
},
processEvent: function (type, view, cell, rowIndex, cellIndex, e, record) {
if (type == "mousedown" && e.getTarget('.' + Ext.baseCSSPrefix + 'grid-row-expander')) {
me.toggleRow(rowIndex, record);
return me.selectRowOnExpand;
}
}
};
}
});
This is not what I wanted to do, but I looked at the source code for the plugin and I see no way to hook the renderer.
I have a dgrid assigned to a REST service with JSON.
It works fine.
I have a filterselect in one of the columns.
The filterselect is populated from another dojo store.
My question is, how can I disable the filterselect when it's value is for example 10?
I tried canEdit, but it does not work.
Any suggestions?
Thanks!
Editor({
label: 'Size', autoSave: true, field: 'picsubtype',
canEdit: function(object, value) {
return value != 10;
},
widgetArgs: {
store: filesubtypeStore, maxHeight: 150, style: "height: 20px;"
},
}, FilteringSelect)
This code does not work...
Have you tried setting up a onChange handler in the widgetArgs?
Something like:
onChange: function(newValue) { if(newValue === 10) { this.set('disabled', true); } }
But how would the widget get re-enabled?