View is not rendering in Backbone.js - backbone.js

I'm trying to render a search box on my page. I'm trying to keep it in a seperate view. The page without this boxview is working correctly but as soon as i initialize my BoxView i get the error related to underscore.
Uncaught TypeError: Object [object Object] has no method 'replace' underscore-min.js:29
Here is my View
/* Views */
var BoxView = Backbone.View.extend({
el: '.head',
initialize: function() {
this.render();
},
render : function(){
var that = this;
var template = _.template($('#search-box').html());
that.$el.html(template);
}
});
var boxview = new BoxView();
Template
<script type="text/template" id="search-box">
<form class="navbar-search pull-right" id="search">
<input class="search-query" name="searchText" type="text" id="searchText" placeholder="Search books"/>
<button type="submit" class="btn">Submit</button>
</form>
</script>
EDIT :
Removed the typo error

It seems to me it's just a typo:
var template = _.template($('#search-box')).html();
should be:
var template = _.template($('#search-box').html());
Edit:
I'd normally assume this is the kind of typo made while writing the question, but your error suggests the problem comes from an underscore call (you only have one), and that it's trying to use replace on an object. _.template surely uses replace and you give it an object ($('#search-box')). So it makes sense.

Related

jQuery UI Dialog with angularjs

I am trying to write a functionality where if we pass the scope and template, it should show the given template in a jQuery UI dialog with the all working bindings from the given scope.
Here is the code:
HTML
<div id="mainDiv" ng-controller="myCtrl">
<input type="button" value="show dialog" ng-click="showTemplateDialog()" />
</div>
<script type="text/ng-template" id="dialogTemplate">
<div>
This is template div.
<span>Message: </span>
<p>{{message}}</p>
</div>
</script>
JS
var app = angular.module('myApp', []).controller('myCtrl', function($scope, $compile) {
$scope.showTemplateDialog = function() {
alert("hi")
var newScope = $scope.$new();
newScope.message = "This is some message";
$scope.showDialog(newScope, "dialogTemplate")
};
$scope.showDialog = function(dialogScope, template) {
var div = $("<div style='' id='dialog' title='Test Dialog' ng-include=\"'" + template + "'\"></div>");
$compile(div)(dialogScope);
$("#mainDiv").append(div);
div.dialog();
}
})
The problem is when I call div.dialog(), it throws following error in jquery-ui.min.js
Unhandled exception at line 9, column 26027 in http://localhost/TestApp/scripts/jquery-ui.min.js
0x800a138f - JavaScript runtime error: Unable to get property 'display' of undefined or null reference
Please suggest some way to resolve this error. Or suggest some other way to show and html/template in jQuery dialog using angularjs.
I think the value of div would be a JQuery object. I would try passing the HTML string directly to compile(). The result of compile(html)(scope) is an array IIRC, so you probably want to append its first element [0].
EDIT: I just tried that and it seems Angular won't allow ng-include being compiled this way.
I just tried what Hubert suggested, but still it was not working. Then I realize when I am creating the div, it's not properly getting created and was showing localName of the html element as null.
Then I did some changes in my code and it worked. I just added another div inside the div I was creating and put ng-include on that.
Here is the updated code:
$scope.showDialog = function(dialogScope, template) {
var div = $("<div id='dialog' title='Test Dialog' ><div ng-include=\"'" + template + "'\"></div></div>");
$compile(div)(dialogScope);
$("#mainDiv").append(div);
div.dialog();
}

Why I cannot access form angular's properites in JS such as $error?

I cannot access angular's Form members. I don't have a clue why. I'm using angular 1.4. The full code is at: http://jsbin.com/lujojiduru/edit?html,js,console,output
angular.module('test',[]).controller('testController', function($scope){
$scope.sendInvitations = function(){
var error = myForm.NewInvitations.$error;
console.log('sent');
console.log('value: ' + error );
};
});
the value of $error is always undefined. Any idea?
var error = myForm.NewInvitations.$error;
should be:
var error = $scope.myForm.NewInvitations.$error;
Notice the $scope
This is assuming you have the name="myForm" on your <form> tag
So something like:
<div ng-controller="testController">
<form name="myForm" novalidate>
...
</form>
</div>
you can also, if you prefer, send in the validity of your form, to your method on the controller.
So:
<button class="btn btn-success" ng-click="sendInvitations(myForm.$valid)">Send Invitations</button>
And in your controller:
$scope.sendInvitations = function(isValid){
if(!isValid)
return;
};
Update
You also don't have any errors.
Add required to your input.
So your controller is now:
angular.module('test',[]).controller('testController', function($scope){
$scope.sendInvitations = function(){
debugger;//
var error = $scope.myForm.NewInvitations.$error;
console.log('sent');
console.log(error );
};
});
and your input
<input style="width: 95%" name="NewInvitations" type="email" ng-model="newInvitations" required />
This is an update to your bin
http://jsbin.com/hebikucanu/1/edit?html,js,console,output
myForm is not accessible in the global scope. You can pass it in as an argument to sendInvitations.
ng-click="sendInvitations(myForm)
$scope.sendInvitations = function(myForm){
It's unlikely that you'd need to do this, though. You can do use the myForm properties in the view.
In angular, you should never touch the DOM. Meaning, you should never invoke HTML elements directly as you would in traditional HTML/JS settings. (read more)
Angular encourages the use of ng-model to employ two-way binding as a means to communicate between the controller and the view. (angular two-way data binding tutorial)
Thus, the first change you should attempt is to replace
var error = myForm.NewInvitations.$error;
with:
var error = $scope.NewInvitations;
This will cause the code to run.
But it appears that you want to retrieve the email input validation error and display it through angular.
Here is an excellent explanation with a tutorial that I think achieves what you're trying to do. If you just want to see the code in action, try this link. (Be sure to hit the Run button.)
Hope this helps!

Angular binding model in scope issue?

Hi I am new to the angular js and trying to write the chat application using the socket io and angular js with ionic for android platform. But in my chat page there is one issue.
I am trying to bind the textbox to the $scope.message variable using ng-model but it is not getting bind as the test when i show the same variable value in page itself it works as it is but in controller i gets value as undefined or empty
index.html
<body ng-app="farmApp" ng-controller="farmAppController" >
<ion-content>
<ul id="Messeges">
<li class="right">Welcome to Chat</li>
<li ng-repeat="chatMessage in messages">
{{chatMessage}}
</li>
</ul>
<form ng-submit="sendMessage()">
<input placeholder="Your message" ng-model="message">
<input type="submit" name="send" id="send" value="Send" class="btn btn-success">
<br/>
{{message}} //This updates the value as i type in textbox
</form>
</ion-content>
</body>
but when i see print that model on console it shows undefined when i define at the start in controller then it shows empty value
Controller.js
var farmAppControllers = angular.module('farmAppControllers',[]);
farmAppControllers.controller('farmAppController',['$scope','socket',function($scope,socket){
$scope.messages = [];
$scope.message = ''; //When i don't declare then console shows undefined on sendMessage function if declared then empty
socket.on("update", function (data) {
console.log(data);
$scope.messages.push(data);
});
$scope.sendMessage = function (){
console.log($scope);
console.log($scope.message); // This shows undefined or empty on console
socket.emit("msg",$scope.message);
$scope.messages.push($scope.message);
$scope.message ='';
};
}]);
My app.js
'use strict';
var farmApp = angular.module('farmApp', ['farmAppControllers','farmAppServices','ionic']);
And services.js for socket wrapper
var farmAppServices = angular.module('farmAppServices',[]);
farmAppServices.factory("socket",function($rootScope){
var socket = io.connect();
return {
on:function (eventName,callBack){
socket.on(eventName,function(){
var args = arguments;
$rootScope.$apply(function(){
callBack.apply(socket,args);
});
});
},
emit:function(eventName,data,callBack){
socket.emit(eventName,data,function(){
var args = arguments;
$rootScope.$apply(function(){
if(callBack){
callBack.apply(socket,args);
}
});
});
}
};
});
i stuck here... i try to google it but not able to solve it. In case of confusion feel free to comment. Any help would be great.
UPDATE
When i used the first answer of this question the problem got solved but still not clear why ng-submit is not working ? Any Idea Why ? Because it seems i am still unable to update the view scope from the controller ?
I think the problem is <ion-content> which is a directive and seems to create its own scope. From the docs:
Be aware that this directive gets its own child scope. If you do not understand why this is important, you can read https://docs.angularjs.org/guide/scope.
Therefore your message property isn't in the scope of your controller.
Objects are passed by reference and sendMessage is a function respectively an object, thats why it's still called correctly from the child scope.
What you should do is create an object with a name that makes sense to "package" the properties you want to share.
$scope.package = {}
$scope.package.messages = [];
$scope.package.message = 'You default message...';
And then in your function:
$scope.package.messages.push($scope.package.message);
And in your template:
<input placeholder="Your message" ng-model="package.message">
Here is a plunker with a working solution. It throws some random errors, I actually don't know ionic. But the example works and everything else doesn't matter.

AngularJS ngRepeat Not Updating Display Properly

I have have a page where I am using plupload to upload files and having a weird issue with a ng-repeat not updating properly. Here is the relevant code:
<div ng:app>
<div name="myForm" ng-controller="Ctrl">
<input ng-model="test" type="text" />{{test}}<div id="container" class="controls">
<div id="filelist">
<div ng-repeat="file in filesToUpload">{{file.name}} ({{file.size}}) <b>{{file.percent}}</b></div>
</div>
<br />
<a id="pickfiles" href="#">[Select files]</a>
</div>
</div>
</div>​
function Ctrl($scope) {
$scope.test = '';$scope.filesToUpload = [{id: 1, name: 'test', size: '123kb'}];
$scope.addItem = function(object) {
$scope.filesToUpload.push(object);
}
$scope.uploader = new plupload.Uploader({
runtimes : 'html5,flash,browserplus,gears',
browse_button : 'pickfiles',
container : 'container',
max_file_size : '10mb',
url : 'upload.php',
flash_swf_url : '/plupload/js/plupload.flash.swf'
});
$scope.uploader.init();
$scope.uploader.bind('FilesAdded', function(up, files) {
$scope.filesToUpload = [];
$.each(files, function(i, file) {
$scope.addItem({
id: file.id,
name: file.name,
size: plupload.formatSize(file.size)
});
});
console.log($scope.filesToUpload);
up.refresh(); // Reposition Flash/Silverlight
});
}​
Here is a trimmed down jsfiddle showing the issue happening:
http://jsfiddle.net/9HuUC/
To reproduce this issue do the following:
Click on [select files] and selects a few files (notice how you don't see the files displayed anywhere on the output)
Type any character into the input box (magically the files that you select know appear)
What would cause this type of behavior? I mean I know that the data is properly being set in $scope.filesToUpload because I have the console.log() there and even checked it in Batarang and it loods good there but for some reason something else needs to be updated for the display to be updated.
Interestingly enough, I have another ng-repeat that is working fine on the same page. I am wondering if it has anything to do with where the code is (being inside the FilesAdded event on the uploader).
The issue is due to the fact that the FilesAdded callback is executed outside the scope of AngularJS (it's called by the uploader), therefore the scope updates won't be triggered.
To solve this, just add the $scope.$apply call in the callback, encapsulating your existing code:
$scope.uploader.bind('FilesAdded', function(up, files) {
$scope.$apply( function() {
$scope.filesToUpload = [];
$.each(files, function(i, file) {
$scope.addItem({
id: file.id,
name: file.name,
size: plupload.formatSize(file.size)
});
});
console.log($scope.filesToUpload);
up.refresh(); // Reposition Flash/Silverlight
});
});
With this update, it's working in the fiddle. For reference see the AngularJS official documentation, $apply method of the scope object:
http://docs.angularjs.org/api/ng.$rootScope.Scope

Backbone Underscore Template

So I'm checking out the changes related to the latest backbone/underscore version. Prior I have a project running with BB 0.5.2 and underscore 1.1.7. I'm noticing something strange with regards to defining a template property within a view in the new version, which gives me reservations in going forward with upgrading.
In my current version I would define a view as such:
var MyView = Backbone.View.extend({
template: _.template($('#exampleTemplate').html()),
initialize: function() {...},
render: function() { $(this.el).html(this.template(someObjectParam)); },
});
However, if I attempt to work in the same manner, using a simplified todo clone attempt as an example, I setup an html with an inline script template as such:
<script>
$(document).ready(function() {
app.init();
});
</script>
<script type="text/template" id="itemViewTemplate">
<div class="item">
<input type="checkbox" name="isComplete" value="<%= item.value %>"/>
<span class="description"><%= item.description %></span>
</div>
</script>
In my included JS file I have:
var ItemView = Backbone.View.extend({
el: 'body',
// Below causes error in underscore template, as the jquery object .html() call
// returns null. Commenting will allow script to work as expected.
templateProp: _.template($('#itemViewTemplate').html()),
initialize: function() {
// Same call to retrieve template html, returns expected template content.
console.log($('#itemViewTemplate').html());
// Defining view template property inside here and calling it,
// properly renders.
this.template = _.template($('#itemViewTemplate').html());
this.$el.html(this.template({item: {value: 1, description: 'Something'}}));
},
});
var app = {
init: function() {
console.log('Fire up the app');
var itemView = new ItemView();
}
}
So I'm left confused as to why defining the template property directly causes the call to retrieve the template html to return a null value, thus breaking the attempt to define an underscore template object (mouthful). However, if the definition is done within the initialize function, the call to retrieve the template html properly finds the template so its contents can be passed to the underscore template. Anyone see what I'm potentially missing?
Thanks in advance!
If this:
var ItemView = Backbone.View.extend({
//...
templateProp: _.template($('#itemViewTemplate').html()),
//...
});
is failing because $('#itemViewTemplate').html() is null, then you have a simple timing problem: you're trying to read the content of #itemViewTemplate before it exists. Your old version should suffer from exactly the same problem.
Either make sure everything is loaded in the right order (i.e. your views after your template <script>s) or compile the template in your view's initialize. You can check for the templateProp in your view's prototype and only compile it on first use if you want:
initialize: function() {
if(!this.constructor.prototype.template)
this.constructor.prototype.template = _.template($('#itemViewTemplate').html());
//...
}
Demo: http://jsfiddle.net/ambiguous/HmP8U/

Resources