I am pushing items to a data array and then adding these to a rowData array in order to create custom rows for a table. I need to know how to access these when a user clicks a specific row. I was previously using e.rowData, title etc. for accessing these elements when I had a basic table but now that it is a custom table, this isn't working. Don't worry about the parsing bit, that all works fine. All help appreciated!
data.push({
title: items.item(i).getElementsByTagName("title").item(0).text,
leftImage: str.match(patt1) !== null ? str.match(patt1)[0] : 'image_news.png',
dataToPass: items.item(i).getElementsByTagName("description").item(0).text,
hasChild: true,
js:"external.js"
});
}
var rowData=[];
for(i=0;i<data.length;i++){
var img= Titanium.UI.createImageView({
image:data[i].leftImage,
left:0,
bottom:5,
height: 100,
width: 100
});
var bgBar=Titanium.UI.createView({
height:110,
width: "100%",
bottom:0,
left:0,
backgroundColour: "#000",
opacity: 0.6
});
var title=Titanium.UI.createLabel({
text:data[i].title,
color: 'black',
left: 105
});
var row=Titanium.UI.createTableViewRow({
height: "auto",
hasChild: "true",
js:"external.js",
dataToPass: data[i].dataToPass
});
row.add(img);
row.add(bgBar);
row.add(title);
rowData.push(row);
console.log("row shiznick" + rowData);
}
tableView.setData(rowData);
tableView.addEventListener("click", function (e){
console.log("HERE SOURCE.TITLE ------------------"+e.row.title);
console.log("YOYOOYOYO------------"+e.source.title);
console.log("IS THIS IT---------------"+e.children[0]);
console.log("HERE IS THE SOURCE -----------------------------"+ e.source);
console.log("HERE SOURCE.LEFTIMAGE REG EXP3 ------------------"+e.row.leftImage);
console.log("HERE SOURCE.ClassName ------------------"+e.source.className);
console.log("HERE HASCHILD ------------------"+e.rowData.hasChild);
console.log("HERE DATATOPASS ------------------"+e.row.dataToPass);
});
There are two ways to set the rows of a table, you can create custom rows, or create JSON objects that have the attributes of the row object. Both cases have different ways of accessing the row, either the row object or the rowData object, from the docs:
When the row is created implicitly using a JavaScript dictionary object, use [the rowData property] rather than row to access any custom row properties.
Here's an example of creating a row implicitly, which is not the recommended way.
In your example, since you did not create the row objects implicitly, but explicitly, you can access the clicked row from the row attribute of the event like this:
tableView.addEventListener("click", function(e){
// Get the [TableViewRow](http://docs.appcelerator.com/titanium/latest/#!/api/Titanium.UI.TableViewRow) object
var theRow = e.row;
// Get the children
var rowChildren = theRow.children;
// Here are your objects in the row
var imgInRow = rowChildren[0];
var bgBarInRow = rowChildren[1];
var titleInRow = rowChildren[2];
// Here is the title
var rowTitle = titleInRow.text;
});
Alternatively, in both cases, you could always use the index to look up the row object like this:
tableView.addEventListener("click", function(e){
// Get the index of the row
var ndx = e.index;
// Get the row, this only works if you have not added sections
var row = tableView.data[ndx];
});
For accessing row's datas when user click on (even those which are not displayed in case of custom row for example), you can create an array, push your data in it during the loop and have an access to it with e.index.
A simple code example :
var allDataArray = [];
// loop through each item
for ( var i = 0; i < items.length; i++ )
{
// Your source datas (custom row : id is not displayed in the rows)
var sourceData = {
id: items.item(i).getAttribute('id'),
title: items.item(i).getElementsByTagName("title").item(0).textContent,
};
// Saving data for each loop
allDataArray.push(sourceData);
}
Then accessing the data
itemsTable.addEventListener('click', function(e)
{
// Target the array with e.index offset
var rowContent = allDataArray[e.index];
Ti.API.info(rowContent); // will display every single data of the current row clicked
alert(rowContent.id) // will display the "hidden" id which was not displayed in the UI
}
Try using the event.taget function, something like:
$(".row").click(function(event) {
var element = event.target;
// Accessing element
});
Related
I use SheetJS to upload an excel sheet to a ui.table. While uploading I add a technical ID to my column names, which I will need later on in my project. This is how I am adding the technical ID:
getColumnNames: function(worksheet, aData) {
var firstRow = aData[0];
var oColumns = [];
var cells = Object.keys(worksheet);
for (var i = 0; i < Object.keys(firstRow).length; i++) {
var columnName = Object.keys(firstRow)[i];
var technicalName = "COL" + ('0' + (i+1)).slice(-2);
oColumns.push({
columnId: columnName,
technicalId: technicalName
});
}
return oColumns;
},
When creating the Model, I bind both the columnId and the technicalId to each column.
My users should have the option to reorder the table columns in order to do a mapping to another table. (Context here is not really relevant) So basically there is another table below my uploaded table and a user should be able to reorder the columns of the "uploadTable" to match them with the table below.
Now in order to do a proper mapping, my technical ID has to be adjusted after the reordering is done. Therefore I'd like to add a function that's being executed after the user clicked a "refresh" button.
This function should adjust the technical columnNames. --> E.g. data gets uploaded, column on position 1 has the technical ID "COL01" now it gets dragged to position 2 --> technical ID should change to COL02 and vice versa.
I believe, the only way to do this is by accessing the DomRef of the table, because that's the only place where the actual current table structure is stored, but I'm not exactly sure how I would proceed.
My reordering function only gets the data so far:
onReorder : function() {
var table = this.getView().byId("uploadData");
var currentStructre = table.getDomRef();
},
I would appreciate any hints towards this. If anything is unclear, I'm happy to explain it!
sap.ui.table.Table allows its columns to be reordered by dragging and dropping, and the event columnMove is fired after.
One could keep track of and update some sequence label (e.g. ids) using an approach like this:
Remember ids (for example column label as id):
ids = oTable.getColumns().map(oColumn => oColumn.getAggregation('label').getText())
Update ids:
oTable.attachColumnMove(function(oEvent) {
var from = oEvent.getParameter('column').getIndex();
var to = oEvent.getParameter('newPos');
var name = names.splice(from, 1);
names.splice(to, 0, name);
// Then write new ids to model;
})
I am using dojo.gridx to display my values. Sometimes user can create a new row. So that I have added a new button when click newRow button, will call onclick method.
In that method has create new row codes. My codes are below.
addRow:
function() {
var that = this;
var gridIdLocal = dijit.byId('GridId');
that.lastIndex+=1; ( last index count I get externally)
var newRow = {
Id : '',
ClassDES:'',
createdDate: that.getTodayDate(),
activatedDate:that.getTodayDate(),
deactivedDate:'',
activeStatus:'Y',
id : lastIndex
};
gridIdLocal.store.newItem(newRow);
gridIdLocal.store.save();
},
By this code I am able to create a new row but I want to focus my mouse cursor point to newly added row's second column(ClassDES).
How can I achieve this functionality in dojo.gridx?
I havent used Dojo gridx, but looking at one of its basic demos, it is rendering a <table> within <div> for each row. Using newRow object from your example above, you could do something like following with jquery
function() {
var that = this;
var gridIdLocal = dijit.byId('GridId');
that.lastIndex+=1; ( last index count I get externally)
var newRow = {
Id : '',
ClassDES:'',
createdDate: that.getTodayDate(),
activatedDate:that.getTodayDate(),
deactivedDate:'',
activeStatus:'Y',
id : lastIndex
};
gridIdLocal.store.newItem(newRow);
gridIdLocal.store.save();
$(newRow).find("td")[1].children("input").focus();
},
If you could post a working jsfiddle, it would be easier to solve.
I'm trying to get data from app engine datastore using javascript and json. it's also allowed jsonp service, here the javascript code:
$.getJSON("http://1.handy-post-402.appspot.com/show?callback=?", function(json) {
for (var i = 0; i < json.length; i++) {
var map = json[i].propertyMap;
var content = map.isi;
var user = map.No_HP;
var date = map.tanggal;
$('#date').text(date);
$('#nohp').text(user);
$('#content').text(content);
}
});
you can also check it here: http://jsfiddle.net/YYTkK/7/
unfortunately, it just retrieve 1 latest data from the datastore. am I doing something wrong with this code?
thanks in advance.
You're not appending elements, but simply changing the value of the same 3 elements in question three times. So you simply overwrite the value you put into it the time before. The easiest way to solve this is to designate the existing tr as a .template and clone it in your loop, make the necessary changes (filling in the values) and then appending it.
Fixing some other unclear things this gives the following
$.getJSON("http://1.handy-post-402.appspot.com/show?callback=?", function(records) {
for (var i = 0; i < records.length; i++) {
//Clone the row/unit which we will be using for each record (the class should refer to the type of item it /actually/ is)
row = $(".row.template").clone();
//The template class is hidden, so remove the class from the row/unit
row.removeClass("template");
var map = records[i].propertyMap;
var content = map.isi;
var user = map.No_HP;
var date = map.tanggal;
//Make the required changes (find looks for the element inside var row)
row.find('.date').text(date);
row.find('.nohp').text(user);
row.find('.content').text(content);
//Append it to the parent element which contains the rows/units
$("tbody").append(row);
}
});
See functional demo: http://jsfiddle.net/YYTkK/13/
You must append a new row in the table in every loop. Here's the working fiddle.
fiddle
$.getJSON("http://1.handy-post-402.appspot.com/show?callback=?", function(json) {
for (var i = 0; i < json.length; i++) {
var map = json[i].propertyMap;
var content = map.isi;
var user = map.No_HP;
var date = map.tanggal;
var row = '<tr><td>'+date+'</td><td>'+user+'</td><td>'+content+'</td></tr>';
$('#valuetable').append(row);
}
});
what you have to do is create dynamic "tr" s and append to tbody and use thead for header and separate the body using tbody and create tr s on each iteration and after the loop append that tr to tbody. that will do the job, as you do now it will override the values at each iteration.
#chamweer answer is correct you have to create a new tr with td's dynamically
like this:
http://jsfiddle.net/YYTkK/14/
Because you're overriding the same td's over and over again.
$.getJSON("http://1.handy-post-402.appspot.com/show?callback=?", function(json) {
for (var i = 0; i < json.length; i++) {
var map = json[i].propertyMap;
var content = map.isi;
var user = map.No_HP;
var date = map.tanggal;
// create a temporary tr
var tr = $("<tr />");
// append to the tr the td's with their values
tr.append($("<td />").text(date), $("<td />").text(user),
$('<td />').text(content));
// finally append the new tr to the table's tbody
$("#js-tbody").append(tr);
}
});
I have a Kendo UI Grid and I am populating and maintaining the data it displays using Knockout JS (with knockout-kendo.min.js and knockout.mapping-latest.js). When the underlying data updates, the grid also updates to reflect this change. It's working well apart from the problem outlined below.
Code presented in the following Fiddle: http://jsfiddle.net/rTtS9/
The problem is that when the grid updates, it 'forgets' the selected cell that the user has chosen, such that if they are trying to keep an eye on a certain cell value, they can't. If this data is updating sub second (which it could), this gets very silly. The are many other use-case problems too (this is a contrived one).
Is there a way to have the Kendo UI Grid avoid a complete redraw when new data arrives such that the user's selection does not get forgotten?
I thought that this issue might be because KO thought that the whole object had changed, so rather than updating an existing object, it removed and added new ones. To make sure that this isn't the case, I uniquely identify objects using “keys” via the Mapping plugin. In addition, the array remain the same length.
I think that the mapping plugin is working OK as I seem to get desired behavior with the foreach binding, whereby you can select and highlight the ID part of the list item and it won't drop your selection when the data updates. See the Fiddle to see what I mean.
In case this is helpful for anyone else, I have included my solution below which remembers which grid cells were selected before the grid is re-drawn/bound.
I have attached the following code to the Kendo Grid change and dataBound events, respectively. Note, naming conversions for my grid variables always lead with "grid" followed by "name", such as "gridName".
So for the change event:
function saveGridSelection (gridID) {
try {
var shortName = gridID.substring(4,gridID.length)
var idxGrid = ns.grids.map(function(e) {return e.name}).indexOf(shortName);
var gridID = "#grid" + shortName;
var pair=[];
var columnHeader=[];
ns.grids[idxGrid].selectedCells = [];
// Loop over selected realized volsz
$(gridID + " > .k-grid-content .k-state-selected").each(function (index, elem) {
var grid = $(gridID).data("kendoGrid");
var row = $(this).closest("tr");
var colIdx = $("td", row).index(this);
pair[index] = $('td:first', row).text();
columnHeader[index] = $(gridID).find('th').eq(colIdx).text();
if (colIdx != 0 && ns.grids[idxGrid].dataGrid.length > 0 ) { // Check if cell is permitted and has data
pairID = ns.grids[idxGrid].dataGrid.map(function(e) { return e.pair; }).indexOf(pair[index]); // Get the index for the appropriate Pair
ns.grids[idxGrid].selectedCells.push({pair: pairID, container: (colIdx - 1), pairTitle: pair[index], columnHeader: columnHeader[index] });
}
});
} catch (err) {
console.log(err);
}
}
And for the dataBound event:
function loadGridSelection (gridID) {
try {
var shortName = gridID.substring(4,gridID.length)
var idxGrid = ns.grids.map(function(e) {return e.name}).indexOf(shortName);
var gridID = "#grid" + shortName;
var grid = ns.grids[idxGrid];
var gridSelectedCells = grid.selectedCells;
var tempSelectedCells = gridSelectedCells.slice(0); // Create a temp. array to work with
$(gridID + " > div.k-grid-content > table > tbody > tr").each(function (i,e) {
var pair = $("td:nth-child(1)", this).text();
if (tempSelectedCells && typeof tempSelectedCells !== "undefined") {
var ii = tempSelectedCells.length;
while(ii--) { // Loop backwards through teh array so we can slice out the bits we're finished with.
if (pair == tempSelectedCells[ii].pairTitle) {
var row = i;
var column = tempSelectedCells[ii].container;
var noColumns = $(gridID + " > div.k-grid-content > table").find("tr:first td").length;
var cell = (row * noColumns) + 1 + column;
$(gridID).data("kendoGrid").select(gridID + " td:eq("+cell+")");
tempSelectedCells.splice(ii, 1)
}
}
}
});
} catch (err) {
console.log(err);
}
}
Improvements to code always welcome.
i make simple application on titanium using table view. I have some custom row with checkbox on the left side. Here's my code :
var pickingData = [];
for (var i = 0; i<25; i++){
var row = Ti.UI.createTableViewRow({
className:'forumEvent', // used to improve table performance
backgroundSelectedColor:'cyan',
layout:'vertical'
});
if (Titanium.Platform.osname === 'android'){
var checkbox = Ti.UI.createSwitch({
style:Ti.UI.Android.SWITCH_STYLE_CHECKBOX,
value:false,
left:10
});
row.add(checkbox);
}
var rndMatNo = (randomInt(50000)+10000) //randomInt is my random number function
var lblMatNo = Ti.UI.createLabel({
realValue:rndMatNo,
text:'Mat No : ' + rndMatNo,
font:{fontFamily:'Arial', fontSize:DefaultFontSize, fontWeight:'bold'},
left:10,
color:'#222'
});
row.add(lblMatNo);
pickingData.push(row);
}
var tempPickingTable = Titanium.UI.createTableView({
data:pickingData,
editable: Titanium.Platform.osname === 'iphone' ? true : false,
name:'Picking table'
});
tempPickingTable.addEventListener('longclick',function(e){
for (var i=0, length=tempPickingTable.data[0].rows.length;i<length;i++){
if (tempPickingTable.data[0].rows[i].children[0].value === true){
tempPickingTable.deleteRow(i); //Still error when i'm using delete row because index out of bound
}
}
});
all i want is delete the row based on checkbox when it checked. i've tried looping for every row and check the checkbox and then delete the row, but it still give me error index out of bound.
has anyone know how to do that? thanks in advance..
There are some bugs in deleting rows from TableView in Android. You can try to create a new data array with all the rows except the ones that have been checked and then set the data for the tableview again.
You're iterating forward through the array, and deleting the rows, which modifies the array, so it makes sense that you'd go out of bounds. Have you tried iterating backwards?
tempPickingTable.addEventListener('longclick',function(e){
for (var i=tempPickingTable.data[0].rows.length;i>=0;i--){
if (tempPickingTable.data[0].rows[i].children[0].value === true){
tempPickingTable.deleteRow(i);
}
}
});