I am new to Backbone, and trying to make a table data using backbone, it has add, edit, delete (CRUD).
In this process I've done the add part, all works fine. But I'm unable to add more than one person using create new list button. Any one assist me to figure out the issue and how to fix this?
Here is the excerpt:
template:
<tbody>
<% _.each(users, function(user){ %>
<tr>
<td><%= user.get("firstName") %></td>
<td><%= user.get("lastName")%></td>
<td><%= user.get("age") %></td>
<td>Edit</td>
</tr>
<%})%>
</tbody>
// function
render:function(){
var template = _.template($("#listTempalate").html(), {users:this.collection.models});
this.$el.html(template)
},
Here is the jsfiddle
Thanks in advance.
When you push the data to your array, you're not adding an id property.
The "created" data are all sharing the same (non-existant) id, and a backbone collection only allows a single instance of the same model (based on the id). So, only the first of the created models is being added to the collection.
What you would do in a real Backbone app is either create a new userModel with the entered data and .add() that to the collection, or just call .add() on the collection with the raw data.
For your demo, you could just generate an id property before you push the data to the array.
Related
Hi I have a situation in AngluarJS that the HTML is generated by back-end and the only thing that front-end should do is to put the HTML which is mostly table tags into the ng-bind-html and show it to the user. But now these tables should be sort-able too. How can I do it?
The thing that I've already done is to create my own directive using this so make the static string HTML take some actions too. But having them sorted is something else. In other word I want to make my fully generated table with all <tr> and <td> to get sorted by my actions.
Here is my simplified code (compile is my directive):
JS:
// The string is fully generated by back-end
$scope.data.html =
'<table> <tr> <th ng-click="sortByHeader($event)"> Name </th>
<th ng-click="sortByHeader($event)"> Age </th> </tr>
<tr> <td> Sara </td> <td> 15 </td> </tr>
<tr> <td> David </td> <td> 20 </td> </tr>'
HTML:
<div compile="data.html"></div>
The ng-click="sortByHeader($event) is something that back-end can prepare for me so I can use it thanks to the compile I wrote that let me find out which header has been clicked. Other than that there is nothing I can do. Unless you can help me :D
Thanks in advance, I hope my question was clear.
Since you tagged your question with sorttable.js I'm going to assume that you are using that script to sort your tables.
Now, if I understand it correctly, sorttable.js parses your HTML for any tables with the class sortable. Your table is apparently loaded dynamically, therefore sorttable.js does not know about it when it parses the HTML.
But you can tell it to make a dynamically added table sortable, too.
Relevant part taken from the following page:
https://kryogenix.org/code/browser/sorttable/#ajaxtables
Sorting a table added after page load
Once you've added a new table to the page at runtime (for example, by
doing an Ajax request to get the content, or by dynamically creating
it with JavaScript), get a reference to it (possibly with var
newTableObject = document.getElementById(idOfTheTableIJustAdded) or
similar), then do this:
sorttable.makeSortable(newTableObject);
You should be able to do that with angular. If not, I can try to put something together later.
Is the answer to the question "Does the rendered table have to exactly match the HTML retrieved by the backend?" a kind of "No"?
If that's the case, then here's a hacky way of gaining control of the table contents by parsing and capturing stuff from the backend HTML string using regular expressions.
For example: grab all row data and apply sorting client side
// Variables to be set by your sortByHeader functions in order to do client-side sorting
$scope.expression = null;
$scope.direction = null;
var regexToGetTableHead = /<table>\s*(.*<\/th>\s*<\/tr>)/g;
$scope.tableHead = regexToGetTableHead.exec($scope.data.html);
$scope.tableRows = [];
var regexToGetRowContents = /<tr>\s*<td>\s*(\w*)\s*<\/td>\s*<td>\s*(\w*)\s*<\/td>\s*<\/tr>/g;
var match;
while ((match = regexToGetRowContents.exec($scope.data.html)) != null) {
$scope.tableRows.push({
"name": match[1],
"age": match[2]
});
}
And HTML
<table>
<thead compile="tableHead"></thead>
<tbody>
<tr ng-repeat="row in tableRows | orderBy: expression : direction">
<td>{{row.name}}</td>
<td>{{row.age}}</td>
</tr>
</tbody>
</table>
I have an array of objects stored in the scope variable. The issue with that is when the user refreshes the page, it does not persist that data, so I am considering using cookies.
The variable $scope.Users stores an array of user objects and I am using the following code to get that data into a cookie:
if ($cookies.getObject('user_data') === '' || $cookies.getObject('user_data') === undefined)
$cookies.putObject('user_data',$scope.Users);
Which does not display any data is I use
console.log($cookies.getObject('user_data'))
and I am not getting anything back, so it seems that putObject does not save the data. What could be wrong here? Could the size of the cookie exceed the limit?
Previously I used the following to retrieve that data from my html page:
<tr ng-repeat="User in Users">
<td>{{User.Name}}</td>
<td>{{User.ID}}</td>
<td>{{User.DOB}}</td>
<td>{{User.Status}}</td>
</tr>
My question is how to I retrieve the array from cookies and display its contents? Also is there a better way to persist an array of objects through refresh? Would service work better?
you can try this code.
var obj = {"Name": name, "ID": id, "DOB": dob, "Status": status};
$scope.Users.push(obj);
$cookies.put('user_data', JSON.stringify($scope.Users));
var s = $cookies.get('user_data');
$scope.Users= JSON.parse(s);
Make sure you inject ngCookies as a dependency to the module,
angular.module('cookiesExample', ['ngCookies'])
You can do this in controller,
To set data
$cookies.user_data = $scope.users;
To retrieve data
$scope.Users= $cookies.user_data;
HTML
<tr ng-repeat="User in Users">
<td>{{User.Name}}</td>
<td>{{User.ID}}</td>
<td>{{User.DOB}}</td>
<td>{{User.Status}}</td>
</tr>
DEMO
I recreated your scenario without issues. What version of $cookies are you using? It should match your angular version.
As for persisting data, the only other option I can think of would be to save it to a server. A service wouldn't work as the refresh would clear it out too.
I followed all the steps described in the docs, I installed smart-table via bower, then I ref the script at index.html, then I added the module to one of my sub-modules, and I created my table:
<table st-table="vm.product_conditions" class="table">
<thead>
<tr>
<th st-sort="name">Nombre</th>
<th st-sort="description">Descripcion</th>
<th st-sort="status">Estado</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="condition in vm.product_conditions track by condition.id"
ng-click="vm.detailProductCondition(condition.id, condition.name)">
<td>{{ condition.name }}</td>
<td>{{ condition.description }}</td>
<td>{{ condition.status ? 'Activa' : 'Inactiva' }}</td>
</tr>
</tbody>
</table>
The table gets populated, but whenever I click on the column in order to sort it, the table gets empty, I also tried to implement the global search, and the same result, empty table...
Also, I get no error output, I tried to reproduce the error in a plunker, but to my surprise It worked there...
Is there any way to debug it?
Are you loading data asynchronous? If you are, you will need to have two collections, one that is the displayed collection and the other that contains all the items for the table.
Smart Table has a data attribute for st-safe-src.
The only way that I believe your tables would return a blank result, is if the product_conditions collection is somehow being interpreted as blank or undefined.
I would attempt to log out the collection to the console, before and after sorting the table and confirm if the collection is the same.
Reason why (from the documentation):
smart-table first creates a safe copy of your displayed collection: it
creates an other array by copying the references of the items. It will
then modify the displayed collection (when sorting, filtering etc)
based on its safe copy. So if you don't intend to modify the
collection outside of the table, it will be all fine. However, if you
want to modify the collection (add item, remove item), or if you load
your data asynchronously (via AJAX-Call, timeout, etc) you will have
to tell smart-table to watch the original collection so it can update
its safe copy. This is were you use the stSafeSrc attribute
I am developing a application in which one of my template renders a table with n number of rows. Now in each row, i have a column with buttons like edit and delete.
When clicked on edit, a edit form appears in the same window in some div. That form needs to be populated with values fetched from backend.
Now nothing great in this.
My problem is this:
I have a view which renders the complete table using the following template structure:
<script type="text/template" id="ledgersing">
<div class="span6 widget">
<div class="widget-header">
<span class="title">Ledgers</span>
<button class="btn btn-danger pull-right" id="addLedgerButton">Add Ledger</button>
</div>
<div class="widget-content">
<table width="100%" class="table table-striped dataTable">
<thead>
<tr><th>Name</th><th>Email</th><th>Phone</th><th>Action</th></tr>
</thead>
<tbody>
<% _.each(ledgers,function(data){ %>
<tr>
<td><%= data.name %></td>
<td><%= data.email %></td>
<td><%= data.contact_number %></td>
<td><span onClick="alert(<%= data.id %>)">x</span></td>
</tr>
<% }) %>
</tbody>
</table>
</div>
</div>
</div >
</script>
In this it just alerts a id when clicked on x. Now do i need to necessarily use onClick event like this? I mean that i will need the id in whatever construct i use for processing. What can be a better solution? I know backbonejs can handle this mess with ease if application is structured properly.
So essentially i want to know from experts, what will they do in such a scenario. How will they structure the application? I am novice to this frontend framework.
Instead of using _.each in your templates, I'd go with one view per table row as each one has some bit of complexity (edit, delete)
In these view, you use the events hash to register your DOM events. Never use onclick in your HTML, this is a really bad practice.
Don't hesitate to look at the TodoMVC Backbone example for ideas on how to organize your app.
I'm also developing a backbone application for the first time and went thru exactly the same mistake.
I first I just tried to translate my php / asp / ruby / whatever_server_side_template_technology into underscore templates, and got something pretty much like what you had.
Now I can realize it's a mistake. You should use subviews. The events and the associated model will be connected to that subview. Pretty soon you'll have lots of view listening to events and updating themselves when data changes, but if you're carefull it will be ok.
Here's a demo app I'm working on: https://bb-jugar.rhcloud.com/index.html#Wine
and here's the github repo: https://github.com/opensas/BackboneBootstrap
This is how I solved it: https://github.com/opensas/BackboneBootstrap/blob/master/demoapp/js/src/views/crud/RowsView.js
I have the following code
<tr>
<th ng-click="predicate='-name'; reverse=false;">Name</th>
<th ng-click="predicate='age'; reverse=true;">Age<th>
<tr>
<tr ng-repeat="user in users | orderBy:predicate:reverse">
<td>{{user.name}}<td>
<td>{{user.age}}</td>
</tr>
My aim here is whenever i click on the table header, then the corresponding column has to be sorted based on particular predicate and reverse. And that is happening perfectly. But I have a scenario where, when i click on an external object, then my age value in table changes here and hence as a result the table sort order is getting disturbed. But i don't want sort to get disturbed. How can i skip table to not obey sort on other actions and have it only on click of table column headers? Can anyone help me with this?
I don't think this is possible. Whenever "users" changes, Angular will notice (since that scope property (i.e., "users") is bound (one-way data binding) to the ng-repeat directive), and Angular will update the view.