currently I'm facing a case where I have to render two properties in the same table cell. So the cell basically looks like this:
columns: [
{
title: 'Customer',
align: 'left',
dataIndex: 'customer.name',
customRender: function(text, record) {
switch (record.customerSatisfaction) {
case "Good":
var good_img = "<img src=...>" // this value comes from a plugin, can't be modified
return good_img + text;
case "Neutral":
var neutral_img = "<img src=...>" // this value comes from a plugin, can't be modified
return neutral_img + text;
case "Unhappy":
var unhappy_img = "<img src=...>" // this value comes from a plugin, can't be modified
return unhappy_img + text;
}
}
},
...] // other columns
As you can see, I want to render customer.name and an image icon that comes from a plugin decided by record.customerSatisfaction. Of course, the render result is plain text without any surprise :(.
What I want here is, an image icon followed by a piece of text. Anyone can help me figure out how to do this?
Related
I'm using ckEditor 5.
My aim is to create a simple search functionality to perform some ajax calls, allow the user to select from a result list and act accordingly (inserting link, or image, or media...).
The problem is that I want to dynamically update the plugin view. Something similar to this: https://github.com/ckeditor/ckeditor5/issues/520, but I'm using a dropdown in the toolbar (I started from the EmbedMedia plugin and didn't care too much about design for now).
I asked the same question on their git (https://github.com/ckeditor/ckeditor5/issues/1681)
My template is like:
this.setTemplate( {
tag: 'form',
attributes: {
class: [
'ck',
'ck-results-form'
],
tabindex: '-1'
},
children: [
this.searchInputView,
this.searchButtonView,
{
tag: 'div',
attributes: {
class: [ 'ck-result-grid' ]
},
children: this.items
},
this.saveButtonView,
this.cancelButtonView,
]
} );
// updateList method is like this:
updateList( valuesArray ) {
console.log(this.items);
this.items = new Array();
console.log(this.items);
for (let i = 0; i < valuesArray.length && i < 20; i++) {
const urlView = new TableSizeGridBoxView(i, valuesArray[i]);
urlView.on('select-url', () => {
this._selectedUrl = valuesArray[i];
});
this.items.push( urlView );
}
console.log(this.items);
//do something here to force refresh or render the section
}
I'm able to get
My expected result, after the search, is to get
and finally select the result.
Currently I can see the object correctly initialized and updated by doing console.log, but the view doesn't update... it stays blank as in the first image (that's why I think there must be something I should be able to put where I wrote //do something here to force refresh or render the section).
Furtermore I can tell that TableSizeGridBoxView is working properly because I'm able to display arbitrary values if I call the for loop in the initialization of the view.
I am using bootstrap data-tables Datatables and bootstrap-taginput with typehead.js. I am new with bootstrap data-tables.
Here is the layout of my bootstrap data-tables Example and please consider Bootstrap tagging input box on top.
I want to search data-tables records with bootstrap tagging elements. but somehow i am unable to search with bootstrap tagging.
Thanks in advance.
If you start out with an empty array of the data you've got on your table you could do something clever by replacing the built in search box. In the example I'm linking to I don't care about one of the columns and the other columns need a little formatting:
var words = [];
var table = $('#example').DataTable({
"columns": [
null, {
"render": function(data, type, row) {
~words.indexOf(data) || words.push(data);
return data;
}
}, {
"render": function(data, type, row) {
var d = data.replace(/\, /g, " ");
~words.indexOf(d) || words.push(d);
return data.split(", ").join("<br/>");
}
}
],
"initComplete": function() {
var searchBox = $("#example_wrapper").find("input[type='search']");
var searchBoxHolder = searchBox.parent();
searchBox.empty().remove();
searchBoxHolder.append($("<input/>", {
"type": "text"
}).typeahead({
source: words,
afterSelect: function(word) {
table.search(word).draw();
}
}).on("keyup", function(x) {
if (words.indexOf($(x.target).val()) === -1) {
table.search($(x.target).val()).draw();
}
}));
}
});
Basically what we're doing here is creating a blank array of search terms then iterating over each second and third cell and adding the term to the array if it doesn't exist. In the case of the third cell I need to clear some formatting (extra comma). Then we get the original search box and it's parent. Remove the original and append the new one to the parent. We then set it up as a typeahead with the list of search terms. We need to make sure it still acts like the original so we add the keyup function. I hope that makes sense.
Working example is here, hope that helps.
I have a problem with dgrid.... I have an AccordionContainer, and in each ContentPane of it,
I place a dgrid. The problems with the dgrid are:
1- Error with scroll: when scrolling down, in certain moment the scroll "skips" and jumps into the end and there's no way to scroll up and show the first records.
(I have seen in Firebug the error TypeError: grid._rows is null when the scroll fails).
2- Trying to change a value: sounds like no dgrid-datachange event is emitted,
no way to capture the event after editing a value.
I think these errors has to do with having dgrid inside layouts (dgrid inside ContentPane, inside AccordionContainer). I also included the DijitRegistry extension but even with this extensions I can't get
rid of this errors.
I have prepared this fiddle which reproduces the errors:
https://jsfiddle.net/9ax3q9jw/5/
Code:
var grid = new (declare([OnDemandGrid, DijitRegistry,Selection, Selector, Editor]))({
collection: tsStore,
selectionMode: 'none',
columns:
[
{id: 'timestamp', label:'Timestamp', formatter: function (value,rowIndex) {
return value[0];
}},
{id: 'value', label: 'Value',
get: function(value){
return value[1];
},
editor: "dijit/form/TextBox"
}
],
showHeader: true
});
grid.startup();
grid.on('dgrid-datachange',function(event){
alert('Change!');
console.log('Change: ' + JSON.stringify(event));
});
//Add Grid and TextArea to AccordionContainer.
var cp = new ContentPane({
title: tsStore.name,
content: grid
},"accordionContainer");
Any help will be appreciated,
Thanks,
Angel.
There are a couple of issues with this example that may be causing you problems.
Data
The store used in the fiddle is being created with an array of arrays, but stores are intended to work with arrays of objects. This is the root of the scrolling issue you're seeing. One property in each object should uniquely identify that object (the 'id' field). Without entry IDs, the grid can't properly keep track of the entries in your data set. The data array can easily be converted to an object array with each entry having timestamp and value properties, and the store can use timestamp as its ID property (the property it uses to uniquely identify each record).
var records = [];
var data = _globalData[0].data;
var item;
for (var i = 0; i < data.length; i++) {
item = data[i];
records.push({
timestamp: item[0],
value: item[1]
});
}
var tsStore = new declare([Memory, Trackable])({
data: records,
idProperty: 'timestamp',
name: 'Temperature'
});
_t._createTimeSeriesGrids(tsStore);
Setting up the store this way also allows the grid column definitions to be simplified. Using field names instead of IDs will allow the grid to call formatter functions with the corresponding field value for each row object.
columns: [{
field: 'timestamp',
label: 'Timestamp',
formatter: function (value) {
return value;
}
}, {
field: 'value',
label: 'Value',
formatter: function (value) {
return value;
},
editor: "dijit/form/TextBox"
}],
Loading
The fiddle is using declarative widgets and Dojo's automatic parsing functionality to build the page. In this situation the loader callback does not wait for the parser to complete before executing, so the widgets may not have been instantiated when the callback runs.
There are two ways to handle this: dojo/ready or explicit use of the parser.
parseOnLoad: true,
deps: [
...
dojo/ready,
dojo/domReady!
],
callback: function (..., ready) {
ready(function () {
var _t = this;
var _globalData = [];
...
});
}
or
parseOnLoad: false,
deps: [
...
dojo/parser,
dojo/domReady!
],
callback: function (..., parser) {
parser.parse().then(function () {
var _t = this;
var _globalData = [];
...
});
}
Layout
When adding widgets to containers, use Dijit's methods, like addChild and set('content', ...). These typically perform actions other than just adding a widget to the DOM, like starting up child widgets.
var cp = new ContentPane({
title: tsStore.name,
content: grid
});
registry.byId('accordionContainer').addChild(cp);
instead of
var cp = new ContentPane({
title: tsStore.name,
content: grid
}, "accordionContainer");
In the example code a ContentPane isn't even needed since the dgrid inherits from DijitRegistry -- it can be added directly as a child of the AccordionContainer.
This will also call the grid's startup method, so the explicit call in the code isn't needed.
registry.byId('accordionContainer').addChild(grid);
It also often necessary to re-layout the grid's container once the grid has been initially rendered to ensure it's properly sized.
var handle = grid.on('dgrid-refresh-complete', function () {
registry.byId('accordionContainer').resize();
// only need to do this the first time
handle.remove();
});
I use dgrid to make a simple grid (http://dojofoundation.org/packages/dgrid/tutorials/defining_grid_structures/).
My question is simple : how to put html tag in label columnheader's ? Because if I put an img tag for example, label contains the string img src=...
Thanks
The column definition can provide a function that builds the column header.
var column = {
//...
renderHeaderCell: function(node) {
domConstruct.create('img', {src: ''}, node);
return node;
}
};
See the documentation of the renderHeaderCell() function in the DGrid wiki:
renderHeaderCell(node)
An optional function that will be called to render the column's header
cell. Like renderCell, this may either operate on the node directly,
or return a node to be placed within it.
One-line answer using put-selector:
renderHeaderCell: function(node) {
return put("img[src=/your/image]");
}
Note this function won't work if your column happens to be a selector - because selector.js defines his own renderHeaderCell(node) function.
#craig Thanks for the answer, in my case I only needed to know how to add HTML into the header cell and the renderHeaderCell(node) was definitely the answer.
For anyone else simply needing to add a <br>, <span>, <div> etc to the header cell, here's a couple of simple examples to compare:
Example without using renderHeaderCell(node):
{
label: 'Title',
field: appConfig.fields[0],
sortable: false
}
Example using renderHeaderCell(node):
{
renderHeaderCell: function(node) {
node.innerHTML = '<span class="headerCell">Title<br><br></span>'
},
field: appConfig.fields[0],
sortable: false
}
Then you can target with CSS as normal:
.headerCell {
font-size: 9px;
}
I have a treegrid "templatecolumn" that displays an image based on a condition in an XTemplate.
However, I also would like an html formatted tooltip displayed upon mouseover of the image. I've done this with Ext JS 3.x via ext:qtip metatdata attribute in a renderer, but haven't been able to figure out how to do this in Ext JS 4.1 using tpl and haven't found anything in my searching.
Here's what I have to display the image based on a record value:
var myTemplate = new Ext.XTemplate(
'<tpl if="p > 0">',
'<img src="exclamation.gif" height="16" width="16"/>',
'</tpl>'
);
var schedTree = Ext.create('Ext.tree.Panel', {
...
columns:[
{ header:' ', dataIndex:'p', xtype:'templatecolumn', tpl:myTemplate }
]
}
Has anyone done this or have any suggestions? Is there a better way to do this? Thanks
This isn't a method using XTemplate, but this one works for me:
{
text : 'Zdj',
width: 40,
align : 'center',
dataIndex : 'Name',
sortable : false,
resizable: false,
renderer: function (v, m, r) {
if(r.get('leaf')==true) {
m.tdAttr = 'data-qtip="<img src=services/Images.ashx?id='+r.get('id')+' width=60px height=60px>"';
return '<img src="services/Images.ashx?id='+r.get('id')+'" width="25px" height="25px"/>';
}
}
},
In my example I'm showing a bigger image in tooltip, but there is no problem to show HTML formatted tooltip.
You can add conditions to renderer and in my opinion do more that XTemplate can do.
Your small image should go to return line and tooltip content to m.tdAttr.
You can read more about renderer function here: http://docs.sencha.com/ext-js/4-1/#!/api/Ext.grid.column.Column-cfg-renderer
Hope this helps :)