Reputation: 4052
I am working on a web application that makes heavy use of grids with select dropdowns for data entry. The grid consists of rows of select boxes. In some situations, there can be hundreds of select boxes on the page at the same time.
At the moment, I render the grid similar to the method below:
function render(jsonData) {
var html = [];
$.each(jsonData.Rows, function (i, row) {
html.push('<tr data-id="', row.Id, '"><td>');
renderSelect(html, globalVar.ArrayX, row.ValueX);
html.push('</td><td>');
renderSelect(html, globalVar.ArrayY, row.ValueY);
html.push('</td><td>');
...
html.push('</tr>');
});
$('tbody#container').html(html.join(''));
}
function renderSelect(html, set, selectedValue) {
html.push('<select>');
$.each(set, function (i, item) {
html.push('<option value="', item.Id, '"', item.Id === selectedValue ? ' selected="1"' : '', '>', item.Name, '</option>');
});
html.push('</select>');
}
Most of the select boxes have the same options, only with different selected items per row (so I can't simply cache the select box html).
Performance is not terrible, Chrome renders the grid in 1 second and FF and IE in about 2. Still I'm wondering, if there may be a more memory/performance efficient alternative to create these select boxes, maybe some way to reference them instead of re-creating them for every row?
Upvotes: 2
Views: 1133
Reputation: 3542
Create the select once and use clone to place it where you need it. If the HTML structure is literally the same, all you'd have to do after that is select the appopropriate value for each select
Your other alternative is to create an html array for the select once before your each statement, join it into a string, and inside the each statement apply it to your the rest of your html picking your the selected option after it's been added. (I hope that made sense.)
Either way writing your row and select box before hand, cloning it (or copying the string) for each loop, and selecting the option separately for each, will be your most performant option.
Here is one possible solution using clone. It doesn't leverage the performance of manipulating strings over appends, but you can come up with an alternate version for your purposes.
// construct your html ahead of time
var rowHtml = [];
rowHtml.push('<tr"><td>');
rowHtml.push('<select>');
$.each(globalVar.ArrayX, function (i, item) {
rowHtml.push('<option value="', item.Id, '"', '>', item.Name, '</option>');
});
rowHtml.push('</select>');
rowHtml.push('</td><td>');
$.each(globalVar.ArrayY, function (i, item) {
rowHtml.push('<option value="', item.Id, '"', '>', item.Name, '</option>');
});
rowHtml.push('</select>');
rowHtml.push('</td><td>');
rowHtml.push('</tr>');
var rowTemplate = $(rowHtml.join(''));
// make a variable for the container once so we can save time performing the DOM lookup
var container = $('tbody#container');
$(jsonData.Rows).each(function (i, row) {
// since I have to do lookups I've chosen to manipulate attributes using jquery
// this should move quickly now that we are just cloning
var clone = rowTemplate.clone();
clone.attr("data-id", row.Id);
$("select option[value=" + row.ValueX + "]", clone).attr("selected", "selected");
container.append(clone);
});
Another alternative, if you don't want to do jquery cloning and lookups would be to do string manipulation where you look for the index of the value="X" statement and insert your selected=selected.
Upvotes: 2