Related
I'm trying to upload image from Camera or gallery. I wrote all the code in the service. The controller must receive the complete url from the camera or gallery to show it in a slide box, but now nothing receive.
Everything works, but I couldn't send back to the controller the url of the image. I think the error is because I'm trying to return the value before that the function "obtenerImagen" execute.
I'm trying to implement Callbacks, but I think I did not implemented correctly.
The variable that I want to return with the url of the image is urlImagen
This is my controller that calls the service:
//generar el popup para seleccionar el origen de la imagen: cámara o galería
function seleccionarImagen() {
cambiarImagenesService.seleccionarImagen()
.then(reemplazarImagen);
}
And the service:
(function() {
'use strict';
angular
.module('example.cambiarimagenes')
.factory('cambiarImagenesService', cambiarImagenesService);
cambiarImagenesService.$inject = ['remoteDataService','$q', '$ionicPopup','$cordovaCamera', '$cordovaFile', '$cordovaFileTransfer', '$cordovaDevice', '$rootScope'];
/* #ngInject */
function cambiarImagenesService(remoteDataService,$q, $ionicPopup, $cordovaCamera, $cordovaFile, $cordovaFileTransfer, $cordovaDevice, $rootScope){
var dias = [];
var mensaje = '';
var image = null;
var urlImagen = '';
var service = {
obtenerHorariosComplejo: obtenerHorariosComplejo,
seleccionarImagen: seleccionarImagen
};
return service;
//cargar una nueva imagen
function seleccionarImagen() {
var popup = seleccionarImagenPopup();
return $ionicPopup.show(popup).then(function(result) {
if (result == -1) {
return false;
}
return urlImagen;
});
}
function obtenerImagen(sourceType, callback){
var options = {
callback: callback,
quality: 100,
destinationType: Camera.DestinationType.FILE_URI,
sourceType: sourceType,
saveToPhotoAlbum: false
};
$cordovaCamera.getPicture(options).then(function(imagePath) {
// Grab the file name of the photo in the temporary directory
var currentName = imagePath.replace(/^.*[\\\/]/, '');
//Create a new name for the photo
var d = new Date(),
n = d.getTime(),
newFileName = n + ".jpg";
// If you are trying to load image from the gallery on Android we need special treatment!
if ($cordovaDevice.getPlatform() == 'Android' && sourceType === Camera.PictureSourceType.PHOTOLIBRARY) {
window.FilePath.resolveNativePath(imagePath, function(entry) {
window.resolveLocalFileSystemURL(entry, success, fail);
function fail(e) {
console.error('Error: ', e);
}
function success(fileEntry) {
var namePath = fileEntry.nativeURL.substr(0, fileEntry.nativeURL.lastIndexOf('/') + 1);
// Only copy because of access rights
$cordovaFile.copyFile(namePath, fileEntry.name, cordova.file.dataDirectory, newFileName).then(function(success){
image = cordova.file.dataDirectory + newFileName;
urlImagen = image;
}, function(error){
$scope.showAlert('Error', error.exception);
});
};
}
);
} else {
var namePath = imagePath.substr(0, imagePath.lastIndexOf('/') + 1);
// Move the file to permanent storage
$cordovaFile.moveFile(namePath, currentName, cordova.file.dataDirectory, newFileName).then(function(success){
image = cordova.file.dataDirectory + newFileName;
urlImagen = image;
}, function(error){
$scope.showAlert('Error', error.exception);
});
}
},
function(err){
console.log("error en el serivicio o cancelacion:"+err);
// Not always an error, maybe cancel was pressed...
})
}
//poopup para cargar nuevo imagen
function seleccionarImagenPopup() {
var scope = $rootScope.$new();
scope.data = {
tipo: null
};
return {
templateUrl: 'scripts/complejo/agenda/nuevo-turno.html',
title: "¿De dónde desea obtener la imagen?",
scope: scope,
buttons: [{
text: 'Cancelar',
onTap: function(e) {
scope.tipo = -1
return scope.tipo;
}
}, {
text: '<b>Cámara</b>',
type: 'button-positive',
onTap: function(e) {
scope.tipo = Camera.PictureSourceType.CAMERA;
obtenerImagen(scope.tipo, function(val){
urlImagen = val;
});
console.log("el valor de la imagen al tocar la camara es:"+image);
return urlImagen;
}
}, {
text: '<b>Galería</b>',
type: 'button-positive',
onTap: function(e) {
scope.tipo = Camera.PictureSourceType.PHOTOLIBRARY;
obtenerImagen(scope.tipo, function(val){
urlImagen = val;
});
console.log("el valor de la imagen al tocar la galeria es:"+image);
return urlImagen;
}
}]
};
}
//generar error si hubo un problema
function generarError(e){
console.log("error!!!!!!:"+e);
if (e.message) {
return $q.reject(e.message);
}
return $q.reject('Ups! Hubo un problema al conectarse al servidor.');
}
}
})();
Thanks for helping me!
//EDIT//
This is now my service:
(function() {
'use strict';
angular
.module('example.cambiarimagenes')
.factory('cambiarImagenesService', cambiarImagenesService);
cambiarImagenesService.$inject = ['remoteDataService','$q', '$ionicPopup','$cordovaCamera', '$cordovaFile', '$cordovaFileTransfer', '$cordovaDevice', '$rootScope'];
/* #ngInject */
function cambiarImagenesService(remoteDataService,$q, $ionicPopup,$cordovaCamera, $cordovaFile, $cordovaFileTransfer, $cordovaDevice, $rootScope){
var dias = [];
var mensaje = '';
var image = null;
var urlImagen = '';
var service = {
obtenerHorariosComplejo: obtenerHorariosComplejo,
seleccionarImagen: seleccionarImagen
};
return service;
//cargar una nueva imagen
function seleccionarImagen() {
var popup = seleccionarImagenPopup();
return $ionicPopup.show(popup).then(function(result) {
if (result == -1) {
return false;
}
return urlImagen;
});
}
function obtenerImagen(sourceType){
var options = {
quality: 100,
destinationType: Camera.DestinationType.FILE_URI,
sourceType: sourceType,
saveToPhotoAlbum: false
};
return $cordovaCamera.getPicture(options).then(function(imagePath) {
// Grab the file name of the photo in the temporary directory
var currentName = imagePath.replace(/^.*[\\\/]/, '');
//Create a new name for the photo
var d = new Date(),
n = d.getTime(),
newFileName = n + ".jpg";
// If you are trying to load image from the gallery on Android we need special treatment!
if ($cordovaDevice.getPlatform() == 'Android' && sourceType === Camera.PictureSourceType.PHOTOLIBRARY) {
window.FilePath.resolveNativePath(imagePath, function(entry) {
window.resolveLocalFileSystemURL(entry, success, fail);
function fail(e) {
console.error('Error: ', e);
}
function success(fileEntry) {
var namePath = fileEntry.nativeURL.substr(0, fileEntry.nativeURL.lastIndexOf('/') + 1);
// Only copy because of access rights
$cordovaFile.copyFile(namePath, fileEntry.name, cordova.file.dataDirectory, newFileName).then(function(success){
image = cordova.file.dataDirectory + newFileName;
return image;
}, function(error){
$scope.showAlert('Error', error.exception);
});
};
}
);
} else {
var namePath = imagePath.substr(0, imagePath.lastIndexOf('/') + 1);
// Move the file to permanent storage
$cordovaFile.moveFile(namePath, currentName, cordova.file.dataDirectory, newFileName).then(function(success){
image = cordova.file.dataDirectory + newFileName;
return image;
}, function(error){
$scope.showAlert('Error', error.exception);
});
}
},
function(err){
console.log("error en el serivicio o cancelacion:"+err);
// Not always an error, maybe cancel was pressed...
})
}
//poopup para cargar nuevo imagen
function seleccionarImagenPopup() {
var scope = $rootScope.$new();
scope.data = {
tipo: null
};
return {
templateUrl: 'scripts/complejo/agenda/nuevo-turno.html',
title: "¿De dónde desea obtener la imagen?",
scope: scope,
buttons: [{
text: 'Cancelar',
onTap: function(e) {
scope.tipo = -1
return scope.tipo;
}
}, {
text: '<b>Cámara</b>',
type: 'button-positive',
onTap: function(e) {
scope.tipo = Camera.PictureSourceType.CAMERA;
var promise = obtenerImagen(scope.tipo)
.then(function(val){
// asignamos el valor asincrónico
urlImagen = val;
// retornamos el valor a la cadena
return val;
});
// retornamos la promesa de manera síncrona
return promise;
}
}, {
text: '<b>Galería</b>',
type: 'button-positive',
onTap: function(e) {
scope.tipo = Camera.PictureSourceType.PHOTOLIBRARY;
var promise = obtenerImagen(scope.tipo)
.then(function(val){
// asignamos el valor asincrónico
urlImagen = val;
// retornamos el valor a la cadena
return val;
});
// retornamos la promesa de manera síncrona
return promise;
}
}]
};
}
//generar error si hubo un problema
function generarError(e){
console.log("error!!!!!!:"+e);
if (e.message) {
return $q.reject(e.message);
}
return $q.reject('Ups! Hubo un problema al conectarse al servidor.');
}
}
})();
The problem is that the callback function is executed asynchronously.
//ERRONEOUS
onTap: function(e) {
scope.tipo = Camera.PictureSourceType.CAMERA;
obtenerImagen(scope.tipo, function(val){
//ASYNCHRONOUSLY ASSIGNED
urlImagen = val;
});
console.log("el valor de la imagen al tocar la camara es:"+image);
//SYNCHRONOUSLY RETURNED
return urlImagen;
}
The value is returned before the value is assigned. Subsequent code executes before the value is defined.
The obtenerImagen function needs to be refactored to return a promise and the promise needs to be returned.
//GOOD
onTap: function(e) {
scope.tipo = Camera.PictureSourceType.CAMERA;
var promise = obtenerImagenPromise(scope.tip)
.then(function(val){
//ASYNCHRONOUSLY ASSIGNED
urlImagen = val;
//return value to chain
return val;
});
//SYNCHRONOUSLY RETURN PENDING PROMISE
return promise;
}
By returning a promise, subsequent code can use the .then method of the promise to delay execution until the value is defined.
Because calling the .then method of a promise returns a new derived promise, it is easily possible to create a chain of promises. It is possible to create chains of any length and since a promise can be resolved with another promise (which will defer its resolution further), it is possible to pause/defer resolution of the promises at any point in the chain. This makes it possible to implement powerful APIs.
-- AngularJS $q Service API Reference - Chaining Promises
Also see SO: Why are Callbacks from Promise .then Methods an Anti-Pattern
what changes shall I need to do in "obtenerImagenPromise" to returns the promise correctly? Because now I have the following error "TypeError: Cannot read property 'then' of undefined" I think I need to return image in the function "obtenerImagenPromise"
Start with returning the derived promise from $cordovaCamera.getPicture:
//function obtenerImagen(sourceType, callback){
function obtenerImagenPromise(sourceType){
var options = {
//callback: callback,
quality: 100,
destinationType: Camera.DestinationType.FILE_URI,
sourceType: sourceType,
saveToPhotoAlbum: false
};
//$cordovaCamera.getPicture(options).then(function(imagePath) {
return $cordovaCamera.getPicture(options).then(function(imagePath) {
//^^^^^^ ---- return derived promise
// Grab the file name of the photo in the temporary directory
The .then method always returns a new derived promise. That promise needs to be returned to the parent function. Also make sure that the functions inside the .then method return a value or promise. Failure to return something will result in the promise resolving as undefined.
I set the returns but always the controller receive undefined
Debugging hint: Put console.log statements to see intermediate values:
//$cordovaCamera.getPicture(options).then(function(imagePath) {
return $cordovaCamera.getPicture(options)
//^^^^^^ ---- return derived promise
.then(
function(imagePath) {
//ADD console.log to see intermediate data
console.log("getPicture success handler called");
console.log("imagePath= "+imagePath);
// Grab the file name of the photo in the temporary directory
var currentName = imagePath.replace(/^.*[\\\/]/, '');
//...
//Always return something
return "something";
},
function(err){
console.log("error en el serivicio o cancelacion:"+err);
// Not always an error, maybe cancel was pressed...
//throw to chain error
throw "error en el serivicio o cancelacion:"+err
}
);
};
Also make sure that the functions inside the .then method return a value or promise. Failure to return something will result in the promise resolving as undefined.
The rule of thumb with functional programming is -- always return something.
You're very close to reach what you want. You have to just call the callback passed to obtenerImagen function.
In your success function:
function success(fileEntry) {
urlImagen = image;
callback(urlImagen);
}
Your callback function already takes the url as parameter.
Replace the function seleccionarImagen in your service with this;
function seleccionarImagen() {
var deferred = $q.defer();
var popup = seleccionarImagenPopup();
$ionicPopup.show(popup).then(function(result){
if(result == -1)
deferred.reject(result);
deferred.resolve(result);
}, function(err){
deferred.reject(err);
});
return deferred.promise;
}
i'm working with Backbone and when I generate the view I have the error Cannot read property 'push' of undefined". The line of the error is "self.subViewsReservas.push(new ReservaView({" in the push.
ReservaCollectionView = Backbone.View.extend({
initialize: function () {
if (Session.get('authenticated') && Session.get('authenticated') !== false) {
this.paginacionVista = new PaginacionReservasView({
collection: this.collection,
el: '.paginacionReservas',
reservasPagina: 5,
});
this.buscadorVista = new BuscadorView({
el: 'div.buscador-reservas',
//Pasamos la colección oficinas ya que hará las veces del conjunto de oficinas retornadas por el servidor
collection: new OficinasCollection(oficinas),
});
}
else {
}
},
render: function () {
var self = this;
this.template = _.template($('#divReservaTpl').html(), {});
self.$('.contenedor-reservas').empty();
self.collection.each(function (reserva, index) {
self.$('.contenedor-reservas').append(self.template({'data': reserva.toJSON()}));
});
this.collection.each(function (reserva, index) {
this.subViewsReservas = [];
self.subViewsReservas.push(new ReservaView({
el: '#' + reserva.get('Idreserva'),
model: reserva
}));
});
this.collection.each(function (reserva, index) {
//Limite de la paginacion 5 limite arbitrario
if (index < 5) {
//Lo Marcamos como visible y actualiazamos la paginación
self.collection.get(reserva.get('Idreserva')).set({'Visibilidad': true});
}
});
this.paginacionVista.render();
return this;
},
});
AppView = Backbone.View.extend({
initialize : function(){
var self = this;
self.usu = new UsuarioModel();
self.usu.fetch({
success: function (model){
Session.fetch({
success : function (){
Session.set('nombre',model.get('Nombre'));
Session.set('apellidos',model.get('Apellidos'));
Session.set('puntos_club',model.get('Puntosclub'));
self.render();
}
});
self.sideBar = new SideBarView({
el : '.sidebar',
model: model
});
self.sideBar.markOption('mis-reservas');
AppView = Backbone.View.extend({
initialize : function(){
var self = this;
self.usu = new UsuarioModel();
self.usu.fetch({
success: function (model){
Session.fetch({
success : function (){
Session.set('nombre',model.get('Nombre'));
Session.set('apellidos',model.get('Apellidos'));
Session.set('puntos_club',model.get('Puntosclub'));
self.render();
}
});
self.sideBar = new SideBarView({
el : '.sidebar',
model: model
});
self.sideBar.markOption('mis-reservas');
},
error : function (){
document.location = '/mygoldcar/login';
}
});
this.listenTo(Session, 'change', self.update);
},
render : function(){
var self = this;
var reservas = new ReservasCollection();
reservas.fetch({
success: function (collection){
if ( typeof collection.models[0].get('error') == 'undefined' || !collection.models[0].get('error')) {
var listRes = new ReservaCollectionView({
el : '.reservas-list',
collection: collection
});
listRes.render();
var popoverModel = new Popover();
popoverModel.setData(collection.models[0].get('kilometraje_ilimitado'), collection.models[0].get('duracion'));
self.popover = new PopoverView({
el: 'body',
model: popoverModel
});
self.popover.establecerPopover();
}
else document.location = '/mygoldcar' + self.urlLang(lang) + '/mi-cuenta/#msg/1';
},
error: function () {
document.location = '/mygoldcar' + self.urlLang(lang) + '/mi-cuenta/#msg/1';
}
});
},
update: function() {
var self = this;
self.sideBar.update(Session.get('nombre'),Session.get('apellidos'),Session.get('puntos_club'));
self.$el.find('.nombre-usuario').text(Session.get('nombre'));
},
updatePoints: function() {
var self = this;
self.usu.fetch({
success: function (model){
Session.set('puntos_club',model.get('Puntosclub'));
}
});
}
}); },
error : function (){
document.location = '/mygoldcar/login';
}
});
this.listenTo(Session, 'change', self.update);
},
render : function(){
var self = this;
var reservas = new ReservasCollection();
reservas.fetch({
success: function (collection){
if ( typeof collection.models[0].get('error') == 'undefined' || !collection.models[0].get('error')) {
var listRes = new ReservaCollectionView({
el : '.reservas-list',
collection: collection
});
listRes.render();
var popoverModel = new Popover();
popoverModel.setData(collection.models[0].get('kilometraje_ilimitado'), collection.models[0].get('duracion'));
self.popover = new PopoverView({
el: 'body',
model: popoverModel
});
self.popover.establecerPopover();
}
else document.location = '/mygoldcar' + self.urlLang(lang) + '/mi-cuenta/#msg/1';
},
error: function () {
document.location = '/mygoldcar' + self.urlLang(lang) + '/mi-cuenta/#msg/1';
}
});
},
update: function() {
var self = this;
self.sideBar.update(Session.get('nombre'),Session.get('apellidos'),Session.get('puntos_club'));
self.$el.find('.nombre-usuario').text(Session.get('nombre'));
},
updatePoints: function() {
var self = this;
self.usu.fetch({
success: function (model){
Session.set('puntos_club',model.get('Puntosclub'));
}
});
}
});
Inside collection.each, this points to the collection. So the property subViewsReservas is added to it, not the view instance. When you try to access it like self.subViewsReservas.push, self points to the view instance, which doesn't have subViewsReservas property, hence the error.
Initializing an array inside each like you're doing isn't doing much since it'll be reset with each invocation of the callback.
You should be initializing it in the initialize method, which is the right place to initialize things, where this will correctly point to the view instance as shown below
initialize: function () {
this.subViewsReservas = [];
}
For some reason if you want the collection to reset everytime, you can change the context to view by passing it as second argument to each like:
this.collection.each(function (reserva, index) {
this.subViewsReservas = [];
self.subViewsReservas.push(new ReservaView({
el: '#' + reserva.get('Idreserva'),
model: reserva
}));
}, self); // <--- makes view the context of callback,
// both 'self' and 'this' will refer to view
I have this simple BackboneJS app and it keeps returning this error on adding new model to collection: Cannot call method 'on' of undefined. Can someone help me. I can't see the problem in here.I have my templates defined in index.html, and I am using Slim framework and NotORM.
(function(){
window.App =
{
Models:{},
Collections: {},
Views : {}
}
window.template = function(id)
{
return _.template( jQuery('#' + id).html());
}
App.Models.Party = Backbone.Model.extend({
});
App.Collections.Partys = Backbone.Collection.extend({
model: App.Models.Party,
url: "http://localhost/BackboneJS/vjezba6/server/index.php/task"
});
App.Views.Party = Backbone.View.extend({
tagName :"div",
className: "box shadow aktivan",
template: template("boxovi"),
initialize: function()
{
this.model.on('change', this.render, this);
},
events:{
"click .izbrisi" : "izbrisi"
},
render: function()
{
var template = this.template( this.model.toJSON() );
this.$el.html(template);
return this;
},
izbrisi: function()
{
this.model.destroy();
},
ukloni: function()
{
this.remove();
}
});
App.Views.Partys = Backbone.View.extend({
tagName:"div",
id: "nosac-boxova",
initialize: function()
{
},
render: function() {
this.collection.each(this.addOne, this);
return this;
},
addOne: function(party) {
var partyView = new App.Views.Party({ model: party });
this.$el.append(partyView.render().el);
}
});
App.Views.Dodaj = Backbone.View.extend({
tagName: "div",
template : template("dodajTemp"),
events:
{
'submit' : 'submit'
},
submit : function(e)
{
e.preventDefault();
console.log(e);
var nazivPolje = $(e.currentTarget).find(".naziv").val();
var tekstPolje = $(e.currentTarget).find(".lokal").val();
var noviParty = new App.Views.Party({naziv:nazivPolje, tekst: tekstPolje});
this.collection.create(noviParty);
},
initialize: function()
{
},
render: function()
{
var template = this.template();
this.$el.html(template);
return this;
}
});
/* var kolekcijaPartya = new App.Collections.Partys([
{
naziv:"Ovo je prvi naziv",
tekst: "Ovo je prvi tekst"
},
{
naziv:"Ovo je drugi naziv",
tekst: "Ovo je drugi tekst"
}
]);*/
var kolekcijaPartya = new App.Collections.Partys;
kolekcijaPartya.fetch({
success: function()
{
var partysView = new App.Views.Partys({collection:kolekcijaPartya});
$("#content").prepend(partysView.render().el);
$("div.box").slideAj();
var dodajView = new App.Views.Dodaj({collection: kolekcijaPartya});
$("div#sidebar-right").html(dodajView.render().el);
}
});
})();
var noviParty = new App.Views.Party({naziv:nazivPolje, tekst: tekstPolje});
this.collection.create(noviParty);
so you are trying to add a View to your collection?
console.log('Loaded inedx.js-->');
console.log(jQuery);
(function($){
console.log('In immediate block');
//Create new tweet view
var Tweet = Backbone.Model.extend({
defaults: function(){
return {
name : 'defaultName',
status : 'default status'
}
}
});
var TweetList = Backbone.Collection.extend({
model :Tweet
});
var TweetView = Backbone.View.extend({
model : new Tweet(),
tagName : 'div',
initialize : function(){
this.template = _.template($('#tweet-template').html());
},
render : function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
var tweets = new TweetList();
var TweetsView = Backbone.View.extend({
model : tweets,
tagName : 'div',
el : $('#allTweetContainer'),
initialize: function(){
this.model.on('add',this.render,this);
},
render : function(){
var self = this;
_.each(this.model.toArray(),function(tweet,i){
self.$el.append((new TweetView({model:tweet})).render().$el.html());
});
return this;
}
});
$(document).ready(function (){
tweets.add(new Tweet({
status : 'status1',
author : 'author1'
}));
var tweet = new Tweet({
status : 'status1-----',
author : 'author1-------'
});
//console.log(new TweetView());
//$('#allTweetContainer').append( _.template($('#tweet-template').html(),tweet.toJSON()));
tweets.add(new Tweet({
status : 'status2',
author : 'author2'
}));
tweets.add(new Tweet({
status : 'status3',
author : 'author3'
}));
tweets.add(new Tweet({
status : 'status4',
author : 'author4'
}));
var tweetApp = new TweetsView();
tweetApp.render();
console.log(tweets.toJSON());
});
})(jQuery);
I am not able to render TweetsView.
Instead of : self.$el.append
When I used : `$('#allTweetContainer').append
it worked. But ideally it should work with self.$el.append.
I believe there must be something extra needs to be done to get proper $el which should be a jQuery variable pointing to the given el.
Any pointers would really helpful. Thanks in advance.
You should declare el as string and not as jQuery selector. So your TweetsView should look like this:
var TweetsView = Backbone.View.extend({
model : tweets,
tagName : 'div',
el : '#allTweetContainer',
initialize: function(){
this.model.on('add',this.render,this);
},
render : function(){
var self = this;
_.each(this.model.toArray(),function(tweet,i){
self.$el.append((new TweetView({model:tweet})).render().$el.html());
});
return this;
}
});
when appending the TweetView to TweetsView, you could also do this:
_.each(this.model.toArray(),function(tweet,i){
self.$el.append((new TweetView({model:tweet})).render().el);
});
I am developing a Backbone web application and I want to know that how can post data from the view
This is my Model:
App.Models.edit = Backbone.Model.extend({
defaults : {
id : undefined,
fname : undefined,
lname : undefined,
phone : undefined,
address : undefined,
email : undefined,
url: undefined,
},
initialize: function(){
this.set({url : '../api/getOne/' + App.CurrentID });
},
getAttrs: function(attr){
return this.get(attr);
}
});
And this is my view:
App.Views.edit = Backbone.View.extend({
el: $("#modal"),
initialize: function(){
App.TplNames.edit = $('body');
App.Tpls.edit('edit');
this.model.bind("reset", this.render, this);
this.render();
},
events: {
'click .btnSave': 'saveDetails',
},
saveDetails: function(){
this.model.save();
//console.log(this.model);
},
render: function(){
var elem = '';
$.each(this.model.models, function(i, k){
var template = _.template( $('#tpl_edit').html(), k.toJSON() );
elem += template;
});
$(this.el).html(elem);
$("#myModal").modal('show');
$("#myModal").on('hidden', function(){
//alert(123);
document.location.href = App.Url + '#view';
});
var attrs = "";
$.each(this.model.models, function(i, k){
attrs = k.toJSON();
});
$("#fname").val(attrs.fname);
$("#lname").val(attrs.lname);
$("#Email").val(attrs.email);
$("#Phone").val(attrs.phone);
$("#Address").val(attrs.address);
//console.log(attrs);
}
});
And it is my Router
App.Router = Backbone.Router.extend({
routes: {
"" : "def",
"home" : "def",
"view" : "getAll",
"edit/:id" : "edit",
"add" : "addContact",
},
def: function(){
this.mainModel = new App.Collections.Main();
this.mainView = new App.Views.Main({model: this.mainModel});
//this.mainModel.fetch();
},
edit: function(id){
App.CurrentID = id;
var contactCollObj = new App.Collections.edit();
viewObj = new App.Views.edit({model: contactCollObj});
contactCollObj.fetch();
viewObj.render();
//console.log(contactCollObj);
},
getAll: function(){
//alert(123);
var collObj = new App.Collections.View();
var viewObj = new App.Views.View({model: collObj});
collObj.fetch();
},
addContact: function(){
//var model = new App.Collections.AddContact();
model = new App.Models.AddContact();
var view = new App.Views.AddContact({model: model});
//view.render();
}
});
var app = new App.Router();
Backbone.history.start();
And when I want to save the model, It generates an error:
this.model.save is not a function
Every thing is okay except the above...
In your router you pass collection to App.Collections.edit view as model:
var contactCollObj = new App.Collections.edit();
viewObj = new App.Views.edit({model: contactCollObj});
That is why you cannot call save(). save() is only available for a model not a collection.
You probably want to initialize view with collection
viewObj = new App.Views.edit({collection: contactCollObj});
And then also modify some of your view code accordingly.