sorting dynamically created table from html form elemets - javascript

sorry for my english.
I am new at this so i would appreciate a little help here,
I have a html form and its data is shown on my page in html table.
After each new saving form data table sorts by form entry id.
Now i am stuck with sorting and pagination
How can i sort this table data by clicking on column header for some other data, for example by animal_id or animal_name.
Thanks for your help
here is the code:
init: function() {
if (!Animals.index) {
window.localStorage.setItem("Animals:index", Animals.index = 1);
}
Animals.$form.reset();
Animals.$button_discard.addEventListener("click", function(event) {
Animals.$form.reset();
Animals.$form.id_entry.value = 0;
}, true);
Animals.$form.addEventListener("submit", function(event) {
var entry = {
id: parseInt(this.id_entry.value),
animal_id:this.animal_id.value,
animal_name: this.animal_name.value,
animal_type: this.animal_type.value,
bday: this.bday.value,
animal_sex: this.animal_sex.value,
mother_name: this.mother_name.value,
farm_name: this.farm_name.value,
money: this.money.value,
weight: this.weight.value,
purchase_partner: this.purchase_partner.value,
};
if (entry.id == 0) { // add
Animals.storeAdd(entry);
Animals.tableAdd(entry);
}
else { // edit
Animals.storeEdit(entry);
Animals.tableEdit(entry);
}
this.reset();
this.id_entry.value = 0;
event.preventDefault();
}, true);
if (window.localStorage.length - 1) {
var animals_list = [], i, key;
for (i = 0; i < window.localStorage.length; i++) {
key = window.localStorage.key(i);
if (/Animals:\d+/.test(key)) {
animals_list.push(JSON.parse(window.localStorage.getItem(key)));
}
}
if (animals_list.length) {
animals_list.sort(function(a, b)
{return a.id < b.id ? -1 : (a.id > b.id ? 1 : 0);
})
.forEach(Animals.tableAdd);
} }
Animals.$table.addEventListener("click", function(event) {
var op = event.target.getAttribute("data-op");
if (/edit|remove/.test(op)) {
var entry = JSON.parse(window.localStorage.getItem("Animals:"+ event.target.getAttribute("data-id")));
if (op == "edit") {
Animals.$form.id_entry.value = entry.id;
Animals.$form.animal_id.value = entry.animal_id;
Animals.$form.animal_name.value = entry.animal_name;
Animals.$form.animal_type.value = entry.animal_type;
Animals.$form.bday.value = entry.bday;
Animals.$form.animal_sex.value = entry.animal_sex;
Animals.$form.mother_name.value = entry.mother_name;
Animals.$form.farm_name.value = entry.farm_name;
Animals.$form.money.value = entry.money;
Animals.$form.weight.value = entry.weight;
Animals.$form.purchase_partner.value = entry.purchase_partner;
}
else if (op == "remove") {
if (confirm('Are you sure you want to remove this animal from your list?' )) {
Animals.storeRemove(entry);
Animals.tableRemove(entry);
}
}
event.preventDefault();
}
}, true);
},
storeAdd: function(entry) {
entry.id = Animals.index;
window.localStorage.setItem("Animals:index",++Animals.index);
window.localStorage.setItem("Animals:"+entry.id,JSON.stringify(entry));
},
storeEdit: function(entry) {
window.localStorage.setItem("Animals:"+entry.id,JSON.stringify(entry));
},
storeRemove: function(entry) {
window.localStorage.removeItem("Animals:"+ entry.id);
},
tableAdd: function(entry) {
var $tr = document.createElement("tr"), $td, key;
for (key in entry) {
if (entry.hasOwnProperty(key)) {
$td = document.createElement("td");
$td.appendChild(document.createTextNode(entry[key]));
$tr.appendChild($td);
}
}
$td = document.createElement("td");
$td.innerHTML = '<a data-op="edit" data-id="'+ entry.id+'">Edit</a> | <a data-op="remove" data-id="'+ entry.id +'">Remove</a>';
$tr.appendChild($td);
$tr.setAttribute("id", "entry-"+ entry.id);
Animals.$table.appendChild($tr);
},
tableEdit: function(entry) {
var $tr = document.getElementById("entry-"+ entry.id), $td, key;
$tr.innerHTML = "";
for (key in entry) {
if (entry.hasOwnProperty(key)) {
$td = document.createElement("td");
$td.appendChild(document.createTextNode(entry[key]));
$tr.appendChild($td);
}
}
$td = document.createElement("td");
$td.innerHTML = '<a data-op="edit" data-id="'+ entry.id +'">Edit</a> | <a data-op="remove" data-id="'+ entry.id +'">Remove</a>';
$tr.appendChild($td);
},
tableRemove: function(entry) {
Animals.$table.removeChild(document.getElementById("entry-"+ entry.id));
}
};
Animals.init();

Since your current approach is to have your code managing the Table HTML and the Animal data directly, it will need to be your code that does the sorting of the data and the rewrite of the table. That is, you will need to listen for click events on the column headers, and then sort your Animal data according to that particular column, and then redraw the table completely. Redrawing the table could simply entail looping through your tableRemove() and then tableAdd() functions for all Animals being displayed, although that might be a little slow. The sorting of the data by each column is a bit more of a mess for which I have a solution below.
A better approach would be to allow a RIA (Rich Internet Application) Framework to handle the table information for you. Many of these frameworks (EXT-JS, YUI, etc) provide a Table control that will simplify your coding dramatically. You merely give it a reference to your data (formatted in a relevant format), and it will do the sorting and display for you.
If you still want to create the HTML Table yourself, and are more interested in the sorting of the data, then I would suggest going with a Client-side Database solution such as SequelSphere. With SequelSphere, you could create a table to manage your Animal data, as follows:
db.catalog.createTable({
tableName: "animals",
columns: ["id_entry", "animal_id", "animal_name", "animal_type",
"bday", "animal_sex", "mother_name", "farm_name", "money",
"weight", "purchase_partner"],
primaryKey: ["id_entry"]
});
Then you can Insert/Update/Delete rows like this:
db.catalog.getTable("animals").insertRow(
[ entry.id, entry.animal_id, entry.animal_name, entry.animal_type,
entry.bday, entry.animal_sex, entry.mother_name, entry.farm_name,
entry.money, entry.weight, entry.purchase_partner ]
);
Finally, you can get your data Sorted by whatever column the user clicked by merely changing the ORDER BY clause in the following select statement:
var sql = "SELECT id_entry, animal_id, animal_name, animal_type, " +
" bday, animal_sex, mother_name, farm_name, money, " +
" weight, purchase_partner " +
" FROM animals " +
" ORDER BY animal_sex "; // why did I choose this column?
var sortedEntries = db.query(sql);
Oh yes: SequelSphere also stores the data in window.localStorage, so you wouldn't have to write that either. It also has full support for SQL and cursors, so managing the Pagination would be a bit easier as well.
Hope this helps!
john...

Related

how can I fetch the Ids from one table to another using the DashboardController and js

i've two tables;
exam_Marks table
{id, codeid, examMarks}
examCodes table
{id, codes, codeDesc}
am trying to fetch the id of codes from table examCodes and pass them to exam_marks table,
however I can't earn this and i don't know where the problem is.
can anyone please help or advice me to use another method
this is my app.js
$scope.examcodesList = function() {
dataFactory.httpRequest(
'dashboard/examcodeList',
'POST',
{},
{"classes":$scope.form.codes}
)
.then(function(data) {
$scope.subje = data.subje;
});
}
and this is my DashboardController.php
public function examcodesList($classes = ""){
$examcodesList = array();
if(!Input::has('classes')){
return $examcodesList;
}
$classes = Input::get('classes');
if(is_array($classes)){
return examcodes::whereIn('id',$classes)->get()->toArray();
}else{
return examcodes::where('id',$classes)->get()->toArray();
}
}
Try with this. Not sure that's what you actually want.
if(is_array($classes)){
return examcodes::join('exam_Marks', 'exam_Marks.codeid', '=', 'examCodes.id')
->whereIn('id',$classes)
->get()->toArray();
}else{
return examcodes::join('exam_Marks', 'exam_Marks.codeid', '=', 'examCodes.id')
->where('id',$classes)
->get()->toArray();
}

Filter JSON object with Array of selected checkbox

How i can filter my JSON object with array.
FIDDLE
This is an sample of my json object and code, i want to filter final render HTML by selected checkbox.
Thanks for your help
function init(arr){
var li = '';
$.each(jsn, function (key, value) {
if (arr.length == 0) {
li += '<li>' + jsn[key].name + '</li>';
}else{
$(arr).each(function (i, v) {
// this section must be filter "pack's" but i can't writ correct query
li += '<li>' + jsn[key].name + '</li>';
});
};
$('#container').html(li);
})
}
var CheckArr = new Array();
init(CheckArr);
$('#btnFilter').click(function(){
var CheckArr = new Array();
$('input[type=checkbox]').each(function () {
if ($(this).is(':checked')) {
CheckArr.push($(this).attr('value'))
}
});
init(CheckArr);
First of all, you have to verify length of array outside of init function. (for case when function is called for first time).Then, you need to iterate your checkboxes array and search every item in your json array(called jsn) to verify condition you need.
Here is solution:
$(document).ready(function(){
var jsn = [
{
"name":"pack01",
"caplessthan100mb":"False",
"cap100to500mb":"True",
"cap500mbto2g":"False",
"cap2gto10g":"False"
},
{
"name":"pack02",
"caplessthan100mb":"True",
"cap100to500mb":"False",
"cap500mbto2g":"False",
"cap2gto10g":"False"
},
{
"name":"pack03",
"caplessthan100mb":"False",
"cap100to500mb":"False",
"cap500mbto2g":"False",
"cap2gto10g":"True"
},
{
"name":"pack04",
"caplessthan100mb":"False",
"cap100to500mb":"False",
"cap500mbto2g":"True",
"cap2gto10g":"False"
},
{
"name":"pack05",
"caplessthan100mb":"False",
"cap100to500mb":"False",
"cap500mbto2g":"False",
"cap2gto10g":"True"
},
{
"name":"pack06",
"caplessthan100mb":"True",
"cap100to500mb":"False",
"cap500mbto2g":"False",
"cap2gto10g":"False"
},
{
"name":"pack07",
"caplessthan100mb":"False",
"cap100to500mb":"False",
"cap500mbto2g":"False",
"cap2gto10g":"True"
}
];
function init(arr){
var li = '';
if(arr.length==0)
{
$.each(jsn, function (key, value) {
li+= '<li>' + jsn[key].name + '</li>';
});
}
else{
$(arr).each(function (i, v) {
$.each(jsn, function (key, value) {
if(jsn[key][v]=="True")
li+= '<li>' + jsn[key].name + '</li>';
});
});
}
$('#container').html(li);
}
var CheckArr = new Array();
init(CheckArr);
$('#btnFilter').click(function(){
var CheckArr = new Array();
$('input[type=checkbox]').each(function () {
if ($(this).is(':checked')) {
CheckArr.push($(this).attr('value'))
}
});
init(CheckArr);
})
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li><input type="checkbox" value="caplessthan100mb">caplessthan100mb</li>
<li><input type="checkbox" value="cap100to500mb">cap100to500mb</li>
<li><input type="checkbox" value="cap500mbto2g">cap500mbto2g</li>
<li><input type="checkbox" value="cap2gto10g">cap2gto10g</li>
<li><input type="button" id="btnFilter" value="Filter"></li>
</ul>
<br />
<ul id="container">
</ul>
There are quite a few things in your code that could use improvement so I've taken the liberty of largely rewriting it (see jsFiddle link below).
1) First thing is in your data (jsn) you are using "False" and "True" instead of false and true. That'll make it hard to write your filter condition because true != "True".
2) It's quite hard to debug your code because the variable names aren't very meaningful. I'd highly recommend putting some energy into improving your variable names especially when code isn't working.
For example:
packsData instead of jsn
checkedBoxes instead of arr
3) If you try to filter within the .each() below you'll run into trouble when it matches more than one filter condition (it'll be displayed more than once).
$(arr).each(function (i, v) {
// this section must be filter "pack's" but i can't writ correct query
li += '<li>' + jsn[key].name + '</li>';
});
Here is a working jsFiddle

Nested ng-repeat in html table

I have a table with three different levels of data, when I call the child level of data using an ng-click the data is diplayed ok but when I call the grandson level the data is not displayed, the response of my WS is ok because I can see it loged in my console so I after some time I realized that I need to nest my ng-repeat's in order to display the data from the grandson level but I don get how to do it, I checked also the ng-repeat-start directive but dont know if it apply to my htlm structure, this is what I have on my view.
<table class="table table-bordered drilldown-table" id="fixTable" style="height: 505px">
<tbody ng-repeat="cat in (exportData.result.slice(0, exportData.result.length-2))" >
<tr class="parent">
<td ng-click="drillDownSubcategoriesCat(cat.merchMetrics.DEPT_NBR,cat.merchMetrics.CATG_GRP_NBR,cat.merchMetrics.DEPT_CATG_NBR)" drill-down>+</td>
<td style="text-align: left">{{cat.merchMetrics.DEPT_CATG_DESC}}</td>
<!--SALES-->
<td>{{cat.merchMetrics.SALES_AMOUNT_LW | number : 2}}</td>
<td>{{cat.merchMetrics.SALES_LW_CHG_LY}}%</td>
<td>{{cat.merchMetrics.SALES_L4W_CHG_LY}}%</td>
<td>{{cat.merchMetrics.SALES_L13W_CHG_LY}}%</td>
<td>{{cat.merchMetrics.SALES_L52W_CHG_LY}}%</td>
<td>{{cat.merchMetrics.SALES_LW_VS_L13W}}</td>
</tr>
<tr ng-repeat="subcat in drillDownSubcatCatList['D' + cat.merchMetrics.DEPT_NBR + 'CG' + cat.merchMetrics.CATG_GRP_NBR + 'C' + cat.merchMetrics.DEPT_CATG_NBR]" class="child" ng-if="!$last" style="background-color: #f3eee9">
<td ng-click="drillDownCategoryItemsCat(subcat.merchMetrics.DEPT_NBR, subcat.merchMetrics.CATG_GRP_NBR, subcat.merchMetrics.DEPT_CATG_NBR, subcat.merchMetrics.DEPT_SUBCATG_NBR)" drill-down>+</td>
<td style="text-align: left; padding-left: 25px">{{subcat.merchMetrics.DEPT_SUBCATG_DESC}}</td>
<!--SALES-->
<td>{{subcat.merchMetrics.SALES_AMOUNT_LW | number : 2}}</td>
<td>{{subcat.merchMetrics.SALES_LW_CHG_LY}}%</td>
<td>{{subcat.merchMetrics.SALES_L4W_CHG_LY}}%</td>
<td>{{subcat.merchMetrics.SALES_L13W_CHG_LY}}%</td>
<td>{{subcat.merchMetrics.SALES_L52W_CHG_LY}}%</td>
<td>{{subcat.merchMetrics.SALES_LW_VS_L13W}}</td>
</tr>
<tr ng-repeat="items in drillDownCategoryItemCatList[nbrSubcatItem]" class="grandson" ng-if="!$last" style="background-color: #f3eee9">
<td></td>
<td style="text-align: left; padding-left: 45px">{{items.merchMetrics.DEPT_SUBCATG_DESC}}}</td>
<!--SALES-->
<td>{{items.merchMetrics.SALES_AMOUNT_LW | number : 2}}</td>
<td>{{items.merchMetrics.SALES_LW_CHG_LY}}%</td>
<td>{{items.merchMetrics.SALES_L4W_CHG_LY}}%</td>
<td>{{items.merchMetrics.SALES_L13W_CHG_LY}}%</td>
<td>{{items.merchMetrics.SALES_L52W_CHG_LY}}%</td>
<td>{{items.merchMetrics.SALES_LW_VS_L13W}}</td>
</tr>
</tbody>
To generate the data from the child and grandson level I call to functions.
$scope.drillDownSubcatCatList = {};
$scope.subcatNbr = '';
$scope.drillDownSubcategoriesCat = function (dept,group,catg) {
$scope.nbr1 = [dept];
$scope.nbr2 = [group];
$scope.nbr3 = [catg];
$scope.nbrSubcat = 'D' + $scope.nbr1 + 'CG' + $scope.nbr2 + 'C' + $scope.nbr3;
$scope.nbrSubcat.toString();
$scope.subCategoryConst = ['Product Sales (Subcategory Rank)'];
$scope.drillDownRecords = "5";
console.log($scope.nbr1);
console.log($scope.nbr2);
console.log($scope.nbr3);
console.log("NBR: " + $scope.nbrSubcat);
if (!($scope.nbrSubcat in $scope.drillDownSubcatCatList)) {
$scope.loadViewCategories = false;
$scope.graphLoading = "loading";
searchFactory.search('merchandise',
{
timeStamp: $scope.dateTime,
timeFrameType: $scope.whenType,
custMembSelectionType: $scope.customerType,
locationSelectionType: $scope.locationType,
merchandiseSelectionType: "Category",
startYear: $scope.whenStartParentYear,
endYear: $scope.whenStartParentYear,
startUnit: $scope.whenStartValue,
endUnit: $scope.whenStartValue,
comparator: $scope.locationType.indexOf('(Comp)', $scope.locationType.length - '(Comp)'.length) !== -1,
locationSelections: $scope.locationSelected,
merchandiseSelections: [$scope.nbrSubcat],
custMembSelections: $scope.customerSelected,
metricSelections: $scope.subCategoryConst,
rankOrder: $scope.drillDownRecords
}).success(function (data) {
console.log("drillDownSubcategories OK");
$scope.loadViewCategories = true;
$scope.graphLoading = "white";
$scope.canvasContent = true;
$scope.exportDataCategoryDrillDown = data;
$scope.metricSelected = $scope.filters.baropt.displayName;
if (data.error) {
$scope.noData = "There are no results based on your selected dropdowns. Please change your selection.";
$scope.data = undefined;
$scope.hasError = true;
}
$scope.isExportDisabled = 'auto';
if (!$scope.drillDownSubcatCatList[$scope.nbrSubcat]) {
$scope.drillDownSubcatCatList[$scope.nbrSubcat] = $scope.exportDataCategoryDrillDown.result;
}
}).error(function (ret, status) {
console.log(ret, status);
if (status == 500 || status == 0) {
if (ret.error.indexOf("Filter criteria not found!") > -1 || ret.error.indexOf("Bad Selections!") > -1) {
$scope.errorMessage = "The combination of dropdowns you selected is invalid. Please select a different combination.";
} else {
$scope.errorMessage = "The database may be down. Please contact Data Cafe Development Team - Applications for help.";
}
} else if (status == 400) {
$scope.errorMessage = "There was a bad request sent to the database. Please contact Data Cafe Development Team - Applications for help.";
} else {
$scope.errorMessage = "There was an error while trying to process your request. Please contact Data Cafe Development Team - Applications for help.";
}
$scope.hasError = true;
$scope.graphLoading = "white";
$scope.canvasContent = true;
$scope.showCaptions = false;
}
);
}
if($scope.nbrSubcat in $scope.drillDownSubcatCatList) {
console.log("--------------- " + $scope.nbrSubcat);
console.log("RETURN DD SUBCATEGORY LIST: ", $scope.drillDownSubcatCatList);
}
}
And this is the second function:
$scope.drillDownCategoryItemCatList = {};
$scope.drillDownCategoryItemsCat = function (dept,group,catg,subcat) {
$scope.nbr1 = [dept];
$scope.nbr2 = [group];
$scope.nbr3 = [catg];
$scope.nbr4 = [subcat];
$scope.nbrSubcatItem = 'D' + $scope.nbr1 + 'CG' + $scope.nbr2 + 'C' + $scope.nbr3 + 'SC' + $scope.nbr4;
$scope.nbrSubcatItem.toString();
$scope.ItemsConst = ['Product Sales (Item Rank)'];
$scope.drillDownRecords = "5";
console.log($scope.nbr1);
console.log($scope.nbr2);
console.log($scope.nbr3);
console.log($scope.nbr4);
console.log("NBR: " + $scope.nbrSubcatItem);
if (!($scope.nbrSubcatItem in $scope.drillDownCategoryItemCatList)) {
$scope.loadViewCategories = false;
$scope.graphLoading = "loading";
searchFactory.search('merchandise',
{
timeStamp: $scope.dateTime,
timeFrameType: $scope.whenType,
custMembSelectionType: $scope.customerType,
locationSelectionType: $scope.locationType,
merchandiseSelectionType: "SubCategory",
startYear: $scope.whenStartParentYear,
endYear: $scope.whenStartParentYear,
startUnit: $scope.whenStartValue,
endUnit: $scope.whenStartValue,
comparator: $scope.locationType.indexOf('(Comp)', $scope.locationType.length - '(Comp)'.length) !== -1,
locationSelections: $scope.locationSelected,
merchandiseSelections: [$scope.nbrSubcatItem],
custMembSelections: $scope.customerSelected,
metricSelections: $scope.ItemsConst,
rankOrder: $scope.drillDownRecords
}).success(function (data) {
console.log("drillDownCategortyItems OK");
$scope.loadViewCategories = true;
$scope.graphLoading = "white";
$scope.canvasContent = true;
$scope.exportDataCategoryItemDrillDown = data;
$scope.metricSelected = $scope.filters.baropt.displayName;
if (data.error) {
$scope.noData = "There are no results based on your selected dropdowns. Please change your selection.";
$scope.data = undefined;
$scope.hasError = true;
}
$scope.isExportDisabled = 'auto';
if (!$scope.drillDownCategoryItemCatList[$scope.nbrSubcatItem]) {
$scope.drillDownCategoryItemCatList[$scope.nbrSubcatItem] = $scope.exportDataCategoryItemDrillDown.result;
}
}).error(function (ret, status) {
console.log(ret, status);
if (status == 500 || status == 0) {
if (ret.error.indexOf("Filter criteria not found!") > -1 || ret.error.indexOf("Bad Selections!") > -1) {
$scope.errorMessage = "The combination of dropdowns you selected is invalid. Please select a different combination.";
} else {
$scope.errorMessage = "The database may be down. Please contact Data Cafe Development Team - Applications for help.";
}
} else if (status == 400) {
$scope.errorMessage = "There was a bad request sent to the database. Please contact Data Cafe Development Team - Applications for help.";
} else {
$scope.errorMessage = "There was an error while trying to process your request. Please contact Data Cafe Development Team - Applications for help.";
}
$scope.hasError = true;
$scope.graphLoading = "white";
$scope.canvasContent = true;
$scope.showCaptions = false;
}
);
}
if($scope.nbrSubcatItem in $scope.drillDownCategoryItemCatList) {
console.log("LIST FROM CATEGORY TO ITEM LEVEL: ", $scope.drillDownCategoryItemCatList);
}
}
As I mentioned before, the parent and the child level are displayed ok, so any idea on how can I nest the ng-repeat's in order to allow my grandson level to be displayed?
There is something strange here that you require a single table in the UI, but the underlying model is of a triply nested object. ng-repeat is not meant to be nested at sibling DOM levels.
The way I would recommend implementing this is to use an angular filter that will wrap all of your data into a single array that you can call ng-repeat on.
Your controller has wayyyyy too much logic in it. And I think this is contributing to the difficulties. In general, the controller should be in charge of displaying data that is being provided by angular services. The angular services should provide the data in a way that is easy for the controllers to consume.
If you find yourself creating nested if statements, xhr requests, and error handling inside of the controller, then you are doing something wrong. All of this should be refactored to several services (each service should have a SINGLE responsibility). Then you should have one of the services provide data to the controller that is easy for it to consume.
This is a bit of a vague answer, and not really a simple one. I think that the problems you are having come from not fully understanding how Angular implements the MVC pattern.

Structuring and Binding (ajax response)

One of the common patterns I've come across in my many years of coding is the structuring/binding of the data coming from the server response (XMLHttpRequest). This problem of creating elements and appending them in a particular order as well as binding (attributes,events,content) is what I'm am trying to achieve here.
For example purposes and simplicity I am trying to create a tr --- td nested structure as well as bind the attributes from the var instructs object (table-row,table-data).
JSON Response (dummy data)
var response =[{"employeeNumber":"1002","lastName":"Murphy","firstName":"Diane","extension":"x5800","email":"dmurphy#classicmodelcars.com","officeCode":"1","reportsTo":null,"jobTitle":"President"},{"employeeNumber":"1056","lastName":"Patterson","firstName":"Mary","extension":"x4611","email":"mpatterso#classicmodelcars.com","officeCode":"1","reportsTo":"1002","jobTitle":"VP Sales"},{"employeeNumber":"1076","lastName":"Firrelli","firstName":"Jeff","extension":"x9273","email":"jfirrelli#classicmodelcars.com","officeCode":"1","reportsTo":"1002","jobTitle":"VP Marketing"},{"employeeNumber":"1088","lastName":"Patterson","firstName":"William","extension":"x4871","email":"wpatterson#classicmodelcars.com","officeCode":"6","reportsTo":"1056","jobTitle":"Sales Manager (APAC)"},{"employeeNumber":"1102","lastName":"Bondur","firstName":"Gerard","extension":"x5408","email":"gbondur#classicmodelcars.com","officeCode":"4","reportsTo":"1056","jobTitle":"Sale Manager (EMEA)"},{"employeeNumber":"1143","lastName":"Bow","firstName":"Anthony","extension":"x5428","email":"abow#classicmodelcars.com","officeCode":"1","reportsTo":"1056","jobTitle":"Sales Manager (NA)"},{"employeeNumber":"1165","lastName":"Jennings","firstName":"Leslie","extension":"x3291","email":"ljennings#classicmodelcars.com","officeCode":"1","reportsTo":"1143","jobTitle":"Sales Rep"},{"employeeNumber":"1166","lastName":"Thompson","firstName":"Leslie","extension":"x4065","email":"lthompson#classicmodelcars.com","officeCode":"1","reportsTo":"1143","jobTitle":"Sales Rep"},{"employeeNumber":"1188","lastName":"Firrelli","firstName":"Julie","extension":"x2173","email":"jfirrelli#classicmodelcars.com","officeCode":"2","reportsTo":"1143","jobTitle":"Sales Rep"},{"employeeNumber":"1216","lastName":"Patterson","firstName":"Steve","extension":"x4334","email":"spatterson#classicmodelcars.com","officeCode":"2","reportsTo":"1143","jobTitle":"Sales Rep"},{"employeeNumber":"1286","lastName":"Tseng","firstName":"Foon Yue","extension":"x2248","email":"ftseng#classicmodelcars.com","officeCode":"3","reportsTo":"1143","jobTitle":"Sales Rep"},{"employeeNumber":"1323","lastName":"Vanauf","firstName":"George","extension":"x4102","email":"gvanauf#classicmodelcars.com","officeCode":"3","reportsTo":"1143","jobTitle":"Sales Rep"},{"employeeNumber":"1337","lastName":"Bondur","firstName":"Loui","extension":"x6493","email":"lbondur#classicmodelcars.com","officeCode":"4","reportsTo":"1102","jobTitle":"Sales Rep"},{"employeeNumber":"1370","lastName":"Hernandez","firstName":"Gerard","extension":"x2028","email":"ghernande#classicmodelcars.com","officeCode":"4","reportsTo":"1102","jobTitle":"Sales Rep"},{"employeeNumber":"1401","lastName":"Castillo","firstName":"Pamela","extension":"x2759","email":"pcastillo#classicmodelcars.com","officeCode":"4","reportsTo":"1102","jobTitle":"Sales Rep"},{"employeeNumber":"1501","lastName":"Bott","firstName":"Larry","extension":"x2311","email":"lbott#classicmodelcars.com","officeCode":"7","reportsTo":"1102","jobTitle":"Sales Rep"},{"employeeNumber":"1504","lastName":"Jones","firstName":"Barry","extension":"x102","email":"bjones#classicmodelcars.com","officeCode":"7","reportsTo":"1102","jobTitle":"Sales Rep"},{"employeeNumber":"1611","lastName":"Fixter","firstName":"Andy","extension":"x101","email":"afixter#classicmodelcars.com","officeCode":"6","reportsTo":"1088","jobTitle":"Sales Rep"},{"employeeNumber":"1612","lastName":"Marsh","firstName":"Peter","extension":"x102","email":"pmarsh#classicmodelcars.com","officeCode":"6","reportsTo":"1088","jobTitle":"Sales Rep"},{"employeeNumber":"1619","lastName":"King","firstName":"Tom","extension":"x103","email":"tking#classicmodelcars.com","officeCode":"6","reportsTo":"1088","jobTitle":"Sales Rep"},{"employeeNumber":"1621","lastName":"Nishi","firstName":"Mami","extension":"x101","email":"mnishi#classicmodelcars.com","officeCode":"5","reportsTo":"1056","jobTitle":"Sales Rep"},{"employeeNumber":"1625","lastName":"Kato","firstName":"Yoshimi","extension":"x102","email":"ykato#classicmodelcars.com","officeCode":"5","reportsTo":"1621","jobTitle":"Sales Rep"},{"employeeNumber":"1702","lastName":"Gerard","firstName":"Martin","extension":"x2312","email":"mgerard#classicmodelcars.com","officeCode":"4","reportsTo":"1102","jobTitle":"Sales Rep"}];
Binding (instructions)
var instructs={
tag:"tr",
attributes:{class:"table-row"},
props:{
email:{
tag:"td",
content: null,
attributes:{class:"table-data",id:"table-data-id"}
},
employeeNumber:{
tag:"td",
attributes:{class:"table-data"},
content: null,
props:{
x:{
tag: "input",
attributes:{class:"table-input"},
content: "test"
}
}
},
extension:{
tag:"td",
content: null,
attributes:{class:"table-data"}
},
firstName:{
tag:"td",
content: null,
attributes:{class:"table-data"}
},
jobTitle:{
tag:"td",
content: null,
attributes:{class:"table-data"}
},
lastName:{
tag:"td",
content: null,
attributes:{class:"table-data"}
},
officeCode:{
tag:"td",
content: null,
attributes:{class:"table-data"}
},
reportsTo:{
tag:"td",
content: null,
attributes:{class:"table-data"}
}
}
};
My Function (assemble)
function assemble(r,s,n){
var n = n || new DocumentFragment();
if(typeof r !== 'string'){ //HAS CHILDREN
r.forEach((o)=>{
for(y in s){
switch(y){
case "tag":
var tag = document.createElement(s[y]);
n.appendChild(tag);
break;
case "attributes":
for(a in s[y]) tag.setAttribute(a,s[y][a]);
break;
case "content":
if(s.content === null){
//append current property value
}
else{
tag.innerHTML = s.content;
}
break;
case "props":
for(k in o) assemble(k,s[y][k],tag); //EXECUTE PER CHILDREN
break;
}
}
});
}
else{
for(x in s){
switch(x){
case "tag":
var tag = document.createElement(s[x]);
n.appendChild(tag);
break;
case "content":
if(s.content === null){
//append current property value
}
else{
tag.innerHTML = s.content;
}
break;
case "attributes":
for(a in s[x]) tag.setAttribute(a,s[x][a]);
break;
case "props":
for(c in s[x]) assemble(r,s[x][c],tag);
break;
}
}
return n;
}
return n;
}
document.addEventListener('DOMContentLoaded',()=>{
var data = assemble(response,instructs);
console.log(data);
});
The end result I'm looking for is an array/fragment of nested tr>td both with a class attribute and the values append to the innerHTML.
<tr class ="table-row">
<td class="table-data">how do I bind the response values?</td>
<td class="table-data">how do I bind the response values?</td>
<td class="table-data">how do I bind the response values?</td>
<td class="table-data">how do I bind the response values?</td>
<td class="table-data">how do I bind the response values?</td>
<td class="table-data">how do I bind the response values?</td>
<td class="table-data">how do I bind the response values?</td>
</tr>
QUESTION:
How can I bind the property values from the response to the innerHTML of the td's?
Give a try to the following one. Sorry, I started refactoring Yours and in the end I had rewritten it. Take care that the content is always taken as innerHTML, it would not be a bad idea at all to differentiate text(append createTextNode func outcome) and html(innerHTML prop). In your data instructs.props.employeeNumber.props.x.content should be moved into instructs.props.employeeNumber.props.x.attributes.value seen how works the input[text] tag. Btw I see there are a lot of stuff that could be discussed here. Hope it helps!
function assemble (data, instr) {
var n = document.createDocumentFragment(), i;
function create(d) {
var objData = d;
return (function _(_instr, _key, _n) {
var innerHTML = !!_key && _key in objData ? objData[_key] : null,
tag = null, i;
if ('tag' in _instr) {
tag = document.createElement(_instr.tag);
tag.innerHTML = 'content' in _instr && !!_instr.content ? _instr.content : innerHTML;
if ('attributes' in _instr) {
for (i in _instr.attributes) tag.setAttribute(i, _instr.attributes[i]);
}
//recur finally
if ('props' in _instr) {
for (i in _instr.props) _(_instr.props[i], i, tag);
}
!!_n && _n.appendChild(tag);
}
return tag;
})(instr, null);
}
return (function (){
for (i in data) {
n.appendChild(create(data[i]));
}
return n;
})();
}
Though my answer does not address the code context from the question, but for structuring and binding json response i usually use regex templating. I find it simple in declaration and concise. ex,
html:
<table>
<tbody id="employee">
</tbody>
</table>
js:
var template = function(tpl, data) {
return tpl.replace(/\$\{([^\}]+)?\}/g, function($1, $2) {
return data[$2];
});
};
var rowTemplate = '<tr class ="table-row">\
<td class="table-data">${email}</td>\
<td class="table-data"><input type="text" value=' ${employeeNumber}' /></td>\
<td class="table-data">${firstName}</td>\
<td class="table-data">${lastName}</td>\
<td class="table-data">${email}</td>\
<td class="table-data">${jobTitle}</td>\
<td class="table-data">${extension}</td>\
</tr>';
var response = [{"employeeNumber":"1002","lastName":"Murphy","firstName":"Diane","extension":"x5800","email":"dmurphy#classicmodelcars.com","officeCode":"1","reportsTo":null,"jobTitle":"President"}, ....]
var b = document.getElementById('employee');
for (var i = 0; i < response.length; i++) {
var tr = document.createElement('x');
b.appendChild(tr);
tr.outerHTML = template(rowTemplate, response[i]);
}
fiddle
hope this helps.

Angular, ng-grid and dynamically populating the grid

I am trying to populate an ng-grid after an AJAX call is returned. The user presses the button to perform a query, and the result is intended to be shown in a grid.
My html is:
<div class="gridStyle" ng-grid="gridOptions" ></div>
And my js is:
app.queryCallback = function(graph) {
var results = graph.toJSON();
var columns = [ns.gtry("hasRank"), ns.gtry("score"), ns.gtry("ks_up"), ns.gtry("ks_down")];
var names = ["Has Rank", "Score", "up", "down"];
$scope.queryData = [];
$.each(results, function(key, values) {
var row = {};
$.each(values, function(uri, dict){
$.each(columns, function(i, column){
if (column == uri) {
row[names[i]] = dict[0]['value'];
}
});
});
$scope.queryData.push(row);
});
$scope.gridOptions = {data : 'queryData'};
$scope.$apply();
}
and my controller is set up as follow:
goiapp.controller('goip', function ($scope) {
var app = this;
However, the grid isn't shown, and with the chrome debugger, I have verified that app.queryData has the correct objects.

Categories