I am creating an application using Marionette and jQuery Mobile and I have a problem with rendered html code.
To compile the html code I use _.template(htmlCode, modelVars) (underscore's method) inside CompositeView's template method.
I write that code to get my goal:
Marionette.CompositeView.extend({
template : function() {
var tpl = App.Templates.get('my-vehicles-table'); //returns html template
return _.template(tpl, {});
},
itemView : Module.View.MyVehicleRow,
itemViewContainer: "tbody"
});
Table rows are rendered by JQM when are defined in tpl variable:
var htmlCode = '<table data-role="table" id="my-vehicles-table" data-mode="reflow" class="ui-responsive table-stroke">
<thead>
<tr class="ui-bar-d">
<th data-priority="2">Reg No.</th>
<th>VIN</th>
<th data-priority="3">Model</th>
<th data-priority="1">Type</th>
<th data-priority="5">Client</th>
</tr>
</thead>
<tbody>
<tr><td>DW 12345</td><td>QWER123</td><td>F12</td><td>No Contract</td><td>John Smith</td></tr>
</tbody>
</table>';
Situatuion is different when tpl is only template for the table (doesn't contain rows):
var tpl = '<table data-role="table" id="my-vehicles-table" data-mode="reflow" class="ui-responsive table-stroke">
<thead>
<tr class="ui-bar-d">
<th data-priority="2">Reg No.</th>
<th>VIN</th>
<th data-priority="3">Model</th>
<th data-priority="1">Type</th>
<th data-priority="5">Client</th>
</tr>
</thead>
<tbody></tbody>
</table>';
And table rows are inserted to <tbody> only by CompositeView methods.
Funny is taht if there are some rows declared in tpl (inside <tbody>) and CompositeView method inserts dynamic other rows, result table has good and bad rendered rows. These are good if were declared in template and those are bad if were added by CompositeView.
What I want? To have all rows rendered by jQuery Mobile (html with special attibutes added to tags when page is rendered).
Thanks!
--- Edit ---
The problem is timing of course. You have to be sure you have fetched all data before rendering a view component (VC). If you want to put data from async request to the VC, before you initialize new instance of it check model's/collection's sync event.
I.e.:
var collection = new CustomCollection();
collection.fetch();
$.when(collection).done(function(collectionRecords){
collectionRecords.on('sync', function() {
//collectionRecords has all the data you want to put into the VC
});
});
Related
I have used bootstrap-table successfully to load AJAX data into a single table using the following call:
function ajaxRequest(params) {
$.getJSON( 'ajax.php?action=doSomething' + $.param(params.data), {format: 'json'}).then(function (res) {
params.success(res)
});
}
But now I'd like to work with multiple tables, each with their own ID, which will be populated by an onClick event bound to a button. Can anyone tell me how I can get the params for any given table required by the function?
The HTML for each table is in the format:
<table id="table-{$id}" class="my-table" data-toggle="table"
data-search="false"
data-ajax="ajaxRequest"
data-side-pagination="server"
data-pagination="true">
<thead>
<tr>
<th data-field="field1" data-sortable="true">Field 1</th>
...
</tr>
</thead>
</table>
Thanks!
I want basically to refresh the data held in a table. First instantiation works just fine, but no luck after removing and re-fetching of the data.
html
<table id="tablePendByOrg" class="table table-bordered table-hover table-condensed table-striped">
<thead>
<tr>
<th data-field="Date">Time</th>
<th data-field="Organization">Org</th>
<th data-field="f24hs"><24Hs</th>
<th data-field="f48Hs"><48Hs</th>
<th data-field="f48Hs">>48Hs</th>
<th data-field="fTotal">Total</th>
</tr>
</thead>
</table>
js to populate after ajax call.
$('#tablePendByOrg').bootstrapTable({
data: d.Table
});
js to remove data
$("#tablePendByOrg tbody tr").remove();
And after a new call to the ajax code, I get the proper data in d.Table but no tbody are showing on the page, just the framed th that I set from the get go.
As they describe:
$table = $('#tablePendByOrg');
$table.bootstrapTable('load', data); // removes old data, no need to remove it by yourself
also the removal o all items is not to be done as you did:
$("#tablePendByOrg tbody tr").remove();
use:
$table.bootstrapTable('removeAll');
I am binding data to a table using Knockout JS and the JQuery/Bootstrap based; Data Table API. The table becomes unresponsive sporadically when sorted or loaded. There are no errors in the log.
It also shows 0 of 0 data as illustrated in the screenshot below:
I have seen similar errors/issues but could not get a solutions for them, E.g. This post:
Code:
function viewModel(){
var self = this;
self.Data = ko.observableArray([]);
$.getJSON('https://restcountries.eu/rest/v1/all', function(data){
self.Data(data);
});
}
ko.applyBindings(viewModel());
$(document).ready(function() {
$('#example').dataTable();
});
HTML:
<div class="table-responsive">
<table id="example" cellspacing="0"
class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th scope="col">Country</th>
<th scope="col">Capital</th>
<th scope="col">Population</th>
<th scope="col">Region</th>
</tr>
</thead>
<tfoot>
<tr>
<th scope="col">Country</th>
<th scope="col">Capital</th>
<th scope="col">Population</th>
<th scope="col">Region</th>
</tr>
</tfoot>
<tbody data-bind="foreach: Data">
<tr>
<td data-bind="text: name"></td>
<td data-bind="text: capital"></td>
<td data-bind="text: population"></td>
<td data-bind="text: region"></td>
</tr>
</tbody>
</table>
</div>
Here is a full working example (JSFiddle) utilizing a REST API so that the exact problem is accurately replicated:
I think the problem with your example may be with how you're dealing with your data when you get it back from the API call.
I've put together a quick example that achieves what I think you're trying to achieve and the sorting and searching work quickly for me.
When I get the JSON data back from the API, I use the Knockout arrayMap utility function to create an array of "Country" objects that have observable properties that I have mapped the JSON data to. I've bound the table to my observableArray of Country objects.
Initialising the data table in the same way you have works fine for me in this case.
The full working solution is here: http://plnkr.co/edit/eroIox6zqBFOVnf86Mdk?p=preview
script.js
var ViewModel = function(jsonData) {
var countries = ko.utils.arrayMap(jsonData, function(item) {
return new Country(item)
});
this.Countries = ko.observableArray(countries);
};
var Country = function(jsonItem) {
this.Name = ko.observable(jsonItem.name);
this.Capital = ko.observable(jsonItem.capital);
this.Population = ko.observable(jsonItem.population);
this.Region = ko.observable(jsonItem.region);
};
window.onload = function() {
$.getJSON('https://restcountries.eu/rest/v1/all', function(data) {
ko.applyBindings(new ViewModel(data));
$("#example").dataTable();
});
}
index.html
<table id="example" cellspacing="0" class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th scope="col">Country</th>
<th scope="col">Capital</th>
<th scope="col">Population</th>
<th scope="col">Region</th>
</tr>
</thead>
<tfoot>
<tr>
<th scope="col">Country</th>
<th scope="col">Capital</th>
<th scope="col">Population</th>
<th scope="col">Region</th>
</tr>
</tfoot>
<tbody data-bind="foreach: Countries">
<tr>
<td data-bind="text: Name"></td>
<td data-bind="text: Capital"></td>
<td data-bind="text: Population"></td>
<td data-bind="text: Region"></td>
</tr>
</tbody>
</table>
Tables are fairly slow to render within Knockout, and if your table is based on a computed, I could see how you could have some issues with redrawing time. But that's not happening here.
Apart from loading the data and binding it to the table rows, there's no data manipulation going on in your viewmodel. All the data manipulation is done by the dataTable plug-in, which you initialize with a single jQuery call. Properly, that should be done within a binding handler. You also need to know what is going on within the plug-in when it sorts, filters, or whatever it does, because you may need to mediate those changes back to your observableArray within your binding handler.
Bottom line: you need a binding handler for the dataTable. There may be one already written; I haven't Googled for it. Give that a try.
I want to create a table that, in its header, contains the names of each player for two teams in each . The scope has a variable teams which is a list of Team objects, each one having list of Player objects as an attribute.
This is turning out to be way harder than I expected.
<table>
<thead>
<tr>
<div ng-repeat="team in teams">
<th ng-repeat="player in team.players">{[ player.name ]}</th>
<th>Partial Score</th>
<th>Total Score</th>
</div>
</tr>
</thead>
</table>
is the easiest thing I have in mind - but this doesn't work. can't be placed inside a according to W3C (from what I understand), so the browser just takes the div and places it outside the table.
I've tried directives as well - but these don't help. This is an example of my directive file.
<th ng-repeat="player in team.players">{[ player.name ]}</th>
<th>Partial Score</th>
<th>Total Score</th>
For example, if I have a <player-initials> directive with replace: 'false', the browser expels the non-<th> element out of the table. Setting replace: 'true', fixes that, but then I get an error because there's more than one root element in the directive. I can't wrap the elements in the directive with anything because that would result in invalid HTML (as above).
I've tried all combinations of element and attribute directives and replace, nothing gives me what I want. Any help?
Created a fiddle here.
Hope this is what you are looking for, if not let me know the format that you are looking for. Your HTML should look something like below.
<table ng-repeat="team in teams">
<tr>
<td colspan="3">
{{team.name}}
</td>
</tr>
<tr>
<td>Player Name</td>
<td>Partial Score</td>
<td>Total Score</td>
</tr>
<tr ng-repeat="player in team.players">
<td>{{player.name}}</td>
<td>{{player.PScore}}</td>
<td>{{player.TScore}}</td>
</tr>
</table>
You should add a method to your scope that do the logic for you.
Something like this should work:
$scope.getAllPlayers = function() {
var players = [];
this.teams.forEach(function(team){
players = players.concat(team.players);
});
return players;
}
Then in your dom:
<table>
<thead>
<tr>
<th ng-repeat="player in getAllPlayers()">{{ player.name }}</th>
<th>Partial Score</th>
<th>Total Score</th>
</tr>
</thead>
</table>
I'm not using Angular so I may be wrong, but I'm pretty sure this is the way to go. This kind of logic have to be in your controller, as simple is a nested loop.
EDIT: Referring to the comments, you could make a function that return your header cells the way you want them
$scope.getHeaderCells = function() {
var cells = [];
this.teams.forEach(function(team){
cells = cells.concat(team.players.map(function(player){
return { team: team, value: player.name };
})).concat([
{team: team, value: 'Partial Score'},
{team: team, value: 'Total Score'}
]);
});
console.log(cells);
return cells;
}
with
<th ng-repeat="cell in getHeaderCells()">{{ cell.value }}</th>
here is a fiddle
I figured it out using the ng-repeat-start and ng-repeat-end directives. I really didn't want to write functions to generate HTML for me, because that's why I switched to Angular in the first place.
Here's a screenshot: http://i.imgur.com/e5LBvQB.png.
This is the (stripped-down to relevant part) code just for the header, everything else is similar. The only 'hacky' part I don't like is the ng-show attributes for B and T to reverse it properly, but it works for me right now. I think I can get clean it up with directives.
<table class="table table-condensed table-striped table-hover table-responsive">
<thead>
<tr>
<th ng-repeat-start="team in game.getTeams()" ng-hide="true"></th>
<th ng-repeat="player in team.getPlayers()" ng-class="$parent.$first && 'text-info' || 'text-danger'">
<u>
{[ player.name | truncate ]}
</u>
</th>
<th ng-repeat-end ng-show="$first">
#
</th>
</tr>
</thead>
</table>
I am using fooTable jQuery plugin as date grid in jQuery mobile. I have list of data I need to populate in the table. Initially with filtering and cell formatting. First I want to populate data in the table. I am using an external .js file to keep JavaScript separately.
HTML5 code, "$.App.initGridView" is not calling from "data-init" tag. Why isn't it working?
<div data-role="view" data-title="Platform" onloadeddata="$.App.initGridView" data-init="$.App.initGridView">
<table class="footable table" id="my-table">
<thead >
<tr data-theme="b">
<th >Ticket#</th>
<th >Date</th>
<th data-hide="phone">Operator Name</th>
<th data-hide="phone">Lease Name</abbr></th>
<th >Tank#</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
jQuery Code:
initGridView: function () {
var rtList = $.App.tempDB.getTicketList();
// I want to populate table here
}