I’m a bit new to canjs. I’ve been working on a generic table can.Component
that has a can.Model
as an attribute property. What I would like to happen is after the component is initialized, it should call the can.Model
's findAll method and load the results into the template as rows. There is additional functionality to allow for editing, adding, and deleting rows.
The findAll is working correctly, and the results are displayed as expected. Likewise, the delete is also working correctly. When a model’s destroy method is called, it is removed from the template. However, updates and creating new rows are not being reflected in the template even though the server requests are successful and returning the expected results.
Here are some snippets from the component:
<!-- template.html -->
{{#if objectsPromise.isPending}}
<p>Loading...</p>
{{/if}}
{{#if objectsPromise.isResolved}}
{{#each objects}}
<tr>
{{#if editable}}
<td class="edit-buttons">
<i ($click)="toggleSelected(.)" class="fa {{#if isSelected(.)}}fa-check-square-o{{else}}fa-square-o{{/if}}"></i>
<i ($click)="editObject(.)" class="fa fa-pencil"></i>
<i ($click)="deleteObject(.)" class="fa fa-trash"></i>
</td>
{{/if}}
{{#each .}}
{{#if renderField(%key)}}
<td>{{formatValue(.)}}</td>
{{/if}}
{{/each}}
</tr>
{{/each}}
{{/if}}
{{#if editable}}
<a href="#" class="btn btn-success" ($click)="createObject">
<i class="fa fa-plus"></i> Add New
</a>
<a href="#" class="btn btn-danger" ($click)="deleteMultiple">
<i class="fa fa-trash"></i> Remove Selected
</a>
{{/if}}
<form ($submit)="formSubmit">
<!-- if there's an edit object, show the form fields -->
{{#if edit_object}}
{{#each edit_object}}
<div class="form-group">
<label for="{{%key}}">{{%key}}</label>
<input type="text" class="form-control" id="{{%key}}" name="{{%key}}" placeholder="" value="{{.}}">
</div>
{{/each}}
<button type="submit" class="btn btn-default">Submit</button>
<a class="btn btn-danger" ($click)="deleteObject(edit_object)">Delete</a>
{{/if}}
</form>
//viewmodel.js
export const ViewModel = viewModel.extend({
define: {
objectModel: {
value: null
},
editable: {
type: 'boolean',
value: false
},
filter: {
type: '*',
value: null
},
group: {
type: 'string',
value: null
},
objectsPromise: {
get: function() {
return this.attr('objectModel').findAll({
filter: this.attr('filter') ? 'q=' + JSON.stringify(this.attr('filter')) : '',
group: this.attr('group') ? 'group=' + this.attr('group') : ''
});
}
},
objects: {
get: function(value, setAttr) {
this.attr('objectsPromise').then(setAttr);
}
},
formSubmit: function(scope, form, event) {
var data = can.$(form).serializeArray();
var edit_object = scope.attr('edit_object');
//update the object with values that changed
for (var i = 0; i < data.length; i++) {
var newData = data[i];
if (edit_object.attr(newData.name) !== newData.value) {
edit_object.attr(newData.name, newData.value);
}
}
scope.attr('edit_object', null);
//prevent the form from submitting
return false;
},
deleteObject: function(obj, skipConfirm) {
if (obj && (skipConfirm || confirm('Are you sure you want to delete this record?'))) {
obj.destroy();
this.attr('edit_object', null);
}
},
createObject: function() {
var newObject = this.attr('objectModel')();
this.attr('editObject', newObject);
},
});
I’ve been stumped on this for a bit, if anyone has a good suggestion, I’d really appreciate your time and advice. Thanks!