How to initialize this object dinamicly after click and bind this in template?
$scope.send = function(){
var setting = {};
var uploader = new FileUploader({
url: settings.path,
alias: settings.alias,
formData: settings.data,
autoUpload: true,
queueLimit: settings.limit
});
}
Than object uploader will be available in template:
<div class="attachements" nv-file-drop="" uploader="uploader"></div>
Now, after loading page I get error, that uploader should be defined:
TypeError: "Uploader" must be an instance of FileUploader
Related
I am learning Backbone.js and as a trial project I am creating a little WordPress user management application. So far my code shows a listing of all WordPress users and it has a form which enables you to add new users to the application.
This all works fine however when you add a new user the listing of users doesn't update automatically, you need to refresh the page to see the new user added which isn't ideal and defeats one of the benefits of Backbone.js!
I have a model for a user and then a collection which compiles all the users. I have a view which outputs the users into a ul and I have a view which renders the form. How do I make my code work so when the .save method is called the view which contains the users updates with the new user? Or is there another way to approach this?
//define the model which sets the defaults for each user
var UserModel = Backbone.Model.extend({
defaults: {
"username": "",
"first_name": "",
"last_name": "",
"email": "",
"password": "",
},
initialize: function(){
},
urlRoot: 'http://localhost/development/wp-json/wp/v2/users'
});
//define the base URL for ajax calls
var baseURL = 'http://localhost/development/wp-json/wp/v2/';
//function to define username and password
function authenticationDetails(){
var user = "myUserName";
var pass = "myPassword";
var token = btoa(user+':'+pass);
return 'Basic ' + token;
}
//add basic authorisation header to all API requests
Backbone.$.ajaxSetup({
headers: {'Authorization':authenticationDetails()}
});
//create a collection which returns the data
var UsersCollection = Backbone.Collection.extend(
{
model: UserModel,
// Url to request when fetch() is called
url: baseURL + 'users?context=edit',
parse: function(response) {
return response;
},
initialize: function(){
}
});
// Define the View
UserView = Backbone.View.extend({
model: UserModel,
initialize: function() {
// create a collection
this.collection = new UsersCollection;
// Fetch the collection and call render() method
var that = this;
this.collection.fetch({
success: function () {
that.render();
}
});
},
// Use an external template
template: _.template($('#UserTemplate').html()),
render: function() {
// Fill the html with the template and the collection
$(this.el).html(this.template({ users: this.collection.toJSON() }));
return this;
},
});
var userListing = new UserView({
// define the el where the view will render
el: $('#user-listing')
});
NewUserFormView = Backbone.View.extend({
initialize: function() {
this.render();
},
// Use an external template
template: _.template($('#NewUserTemplate').html()),
render: function() {
// Fill the html with the template and the collection
$(this.el).html(this.template());
return this;
},
events: {
'click .create-user':'addNewUser'
},
addNewUser: function(){
var newFirstName = $('.first-name').val();
var newLastName = $('.last-name').val();
var newEmail = $('.email').val();
var newPassword = $('.password').val();
var newUserName = newFirstName.toLowerCase();
var myNewUser = new UserModel({username:newUserName,first_name:newFirstName,last_name:newLastName,email:newEmail,password:newPassword});
console.log(myNewUser);
myNewUser.save({}, {
success: function (model, respose, options) {
console.log("The model has been saved to the server");
},
error: function (model, xhr, options) {
console.log("Something went wrong while saving the model");
}
});
}
});
var userForm = new NewUserFormView({
// define the el where the view will render
el: $('#new-user-form')
});
All backbone objects (models, collections, views) throw events, some of which would be relevant to what you want. Models throw change events when their .set methods are used, and Collections throw add or update events... a complete list is here.
Once you know which events are already being thrown, you can listen to them and react. For example, use listenTo - in your view's initialize, you can add:
this.listenTo(this.collection, 'add', this.render);
That will cause your view to rerender whenever a model is added to your collection. You can also cause models, collections, whatever, to throw custom events using trigger from anywhere in the code.
EDIT: For the specific case of getting your user listing view to rerender when a new user is added using the form, here are the steps you can take... In the initialize method of your UserView, after the initialize the collection, add:
this.listenTo(this.collection, 'add', this.render);
Then in your form view... assuming you want to wait until the save is complete on your server, in the addNewUser method, in the success callback of your save, add:
userlisting.collection.add(model);
This will work, since the instance of your UserView is in the global scope. Hope this one works for you!
I have a model that I am using to hold my data in angular:
var FuelProcessingModel = function (carrierService) {
this.myArray = [];
};
That model has an array of MyObjects that I get from the DB:
var MyObject = function () {
//stuff
}
I update this using a REST call:
$scope.add = function () {
var myObject = new MyObject();
fuelProcessingService.add(myObject).then(function(result) {
$scope.model.MyObjects.push(result.data);
});
};
Here you can see I want to push the result to the array so that it is added on the screen. But the problem is the DOM loads before that happens.
service to hit the Server:
this.add = function (myObject) {
var deferred = $q.defer();
$http({
method: "POST",
url: "theServer",
data: myObject,
}).success(function (data) {
deferred.resolve(data);
});
return deferred.promise;
}
The REST service adds to the Database and then returns the updated object
I thought that $q.defer() would cause the DOM to wait to load until the result is returned so that the newly added item shows up.
What am I missing?
UPDATE
I tried doing this but I still have the same problem. The push call is not being called before the DOM loads the page, so the user never sees the added item.
this.add = function (myObject) {
return $http({
method: "POST",
url: "theServer",
data: myObject,
}).success(function (data) {
return data;
});
Html that creates and uses the object
<div ng-repeat="myObject in model.MyObjects" style="margin-bottom: 2%">
//A table of myObjectData
<button class="btn btn-success" ng-click="add()">Add My Object</button>
</div>
Here is what happens in Angular.
Initial html is rendered (also called template html).
Angular boostraps, and then does the necessary binding and the view is updated.
Angular watches for changes and if there is a change in data, view is updated automatically.
When you bind the array to the view the, it renders what is available. When you add some new element to the array later the view should automatically update. You do not need to bother with creating your own promise just do
return $http...
i'm trying to update url without params is it possible ? on my app i created state
.state('webPrint', {
url: '/web/print/:lead',
templateUrl: '/application/views/web-print.html'
})
and when i'm redirecting i'm passing an object
var obj = JSON.stringify(lead);
$state.go('webPrint', { lead: obj });
but my url is something should be like
/web to /web/print but it shows /web/print + "stringify object data" so i changed my code to
$state.go('webPrint', { lead: obj }, { location: false, inherit: false });
but now it's not change url at all. i mean /web to /web
how can i avoid stringify string on url and pass direct to new url?
thanks
You are using option location: false which means you are telling not to change the url.
I would say create a service with getter and setter to save and retrieve your data like below
angular.module('app.service').factory('leadService', function(){
var lead = {};
return{
getLead : function(){
return lead;
},
setLead: function(data){
lead = data;
}
}
});
.state('webPrint', {
url: '/web/print',
templateUrl: '/application/views/web-print.html'
})
var obj = JSON.stringify(lead);
leadService.setLead(obj);
$state.go('webPrint');
Then in your controller get the lead Object using
var lead = leadService.getLead();
I am trying to render a template a template in Typescript, which is not happening. Here's the code and the browser error:
class QuestionView extends Backbone.View{
template: (data:any) => string;
constructor(options?:any){
var question = this;
require(["text!add-new-question.html"],
function(html) {
question.template = _.template(html);
}
);
_.bindAll(this, "render");
}
render(){
var data = this.model.toJSON();
var html = this.template(data);
return this;
}
}
Error:
Uncaught TypeError: Object #<QuestionView> has no method 'template' Main.ts:49
QuestionView.render Main.ts:49
(anonymous function) Main.ts:57
Update:
As pointed out below, this is happening because of the require functions returns after the the render is finished its execution. I've trying running with a setInterval() and it works. How can I make the require function a synchronous one?
You should try using jquery-ajax insted of require.js
var ajxParam: JQueryAjaxSettings = {
async: false, timeout: 200000,
url: "http://somthing", dataType: "html",
cache: false,
success: (htmltext: any, textStatus: string, jqXHR: JQueryXHR) => {
},
error: (jqXHR: JQueryXHR, textStatus: string, errorThrow: string) => {
// show error?
}
}
$.ajax(ajxParam);
//you can bind your data here
i'm trying to connect model and collection using parse.com but i'm confused. I'm tring to fetch by collection using backbone and javascript api parse.com but compare this error:POST https://api.parse.com/1/classes 404 (Not Found).
Model:
var Person = Backbone.Model.extend({
defaults:{
},
initialize:function(){
console.log("inperson");
this.validate();
this.send();
},
validate:function(){
console.log("validate");
},
send:function(){
var user = new Parse.User();
user.set("username", this.get("username"));
user.set("password", this.get("password"));
user.set("email", this.get("email"));
user.signUp(null, {
success: function(user) {
// Hooray! Let them use the app now.
},
error: function(user, error) {
// Show the error message somewhere and let the user try again.
alert("Error: " + error.code + " " + error.message);
}
});
}
});
return Person;
});
Collection:
var Usercollection = Parse.Collection.extend({
model:Person,
initialize:function(){
}
});
return Usercollection;
});
and finally the view that call the colletion and fetch:
var HomeView = Backbone.View.extend({
template: Handlebars.compile(template),
events: {
},
initialize: function() {
console.log("inhomeview");
var amici = new Usercollection();
amici.fetch({
success: function(collection) {
amici.each(function(object) {
console.warn(object);
});
},
error: function(amici, error) {
// The collection could not be retrieved.
}
});
},
render: function() {
}
});
return HomeView;
});
Cant you just swap the backbone collection and model to Parse's ones? (You only used the Parse type of the collection, not the model!)
Try switch that Backbone model to a Parse.Object .
Step by step below:
First of all Lets create a new app on Parse.com, mine is called FunkyAppartments.
Insert the script tag for loading Parse javascript lib into index.html or whathever:
<script src="http://www.parsecdn.com/js/parse-1.5.0.min.js"></script>
Switch the backbone model and collection to use parse types instead (and rename the fetch method if you have extended backbones, since we do not want to overide the one of parse):
//var Appartment = Backbone.Model.extend(); Backbone wo. Parse.com
var Appartment = Parse.Object.extend("Appartment");
//var Appartments = Backbone.Collection.extend({ Backbone wo. Parse.com
var Appartments = Parse.Collection.extend({
model: Appartment,
loadAppartments: function(callback){
debugger;
this.query = new Parse.Query(Appartment);
this.fetch();
}
});
I added a debugger tag in the load appartments so that developer tools breaks in the middle of the controller, here I have access to the Appartment private type of the controller, hence i can store some data on the parse server and verify by pasting the below in the developer tools console.
var testAppartment = new Appartment();
testAppartment.save({name: "foobars"}).then(function(object) {
alert("yay! it worked");
});
Yei, the data shows up in the parse.com UI for the app we just added there. And more importantly it shows up in our frontend. That was easy!
UPDATE: PROBLEMS W BACKBONE 1.2.1, MARIONETTE 2.4.2, UNDERSCORE 1.8.3
I noticed that I actually had been using old versions of marionette, backbone and underscore.js. An initial update appeared to break the application.
After some research i found that it was the parse part that did not return objects that would successfully render. Hence I changed the collection type back to an extension of: Backbone.collection instead of Parse.collection.
I also had to override the query method, since the objects would not save on the correct id, updating an object resulted in a new object being added instead of an old one being updated.
var Apartment = Parse.Object.extend('Appartment');
var Apartments = Backbone.Collection.extend({
model: Apartment,
query: new Parse.Query(Apartment),
initialize: function(){
MyApp.vent.on('search:param', function(param){self.search(param); });
var self = this;
this.query.find({
success: function(results){
self.reset();
results.forEach(function(result){
result.attributes.id__ = result.id
var ap = new Apartment(result.attributes);
self.add(ap);
});
}
});
}
});
I added an attribute: id__ to hold the parse id (naming it just id did not work since it backbone interfered with it, making it disappear).
Finally in saving the model to parse i utilized id__ as id in the save call:
var ApartmentEditView = Backbone.Marionette.ItemView.extend({
template: "#apartment-edit-template",
className: "apartmentDetail",
events: {
"click .store": "storeEdit",
"click .close": "closeEdit"
},
storeEdit: function(){
var priceNum = Number($('#price_field').val().replace(/\s/g, ''));
this.model.set({
id: this.model.attributes.id__,
name:$('#name_field').val(),
price:priceNum,
description:$('#desc_field').val(),
url:$('#url_field').val()
});
this.model.save();
this.closeEdit();
},
closeEdit: function(){
var detailView = new ApartmentDetailView({model: this.model});
MyApp.Subletting.layout.details.show(detailView);
}
});
Now the object is updated correctly in the database.