Angularjs templating: model and function stop working in external templates? - javascript

After this question, I am facing another challenge, the model and function inside the $scope seem have stopped working. Below is the test code, the Add button seem does not collect any data I input from <input type='text' ng-model='newPerson' /> anymore,
html,
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>AngularJS</title>
<meta charset="utf-8">
<script src="js/jquery-1.10.1.min.js"></script>
<script src="js/angular.min.js"></script>
<script src="js/app.js" type="text/javascript"></script>
</head>
<body>
<div ng-app='MyTutorialApp' ng-controller='MainController'>
<div ng-include='thisIsAScopeProperty'></div>
</div>
</body>
</html>
the external template,
<div id='content'>
<input type='text' ng-model='searchText' />
<ul>
<li ng-repeat='person in people | filter:searchText' ng-show='person.live == true'>#{{person.id}} {{person.name}}</li>
</ul>
<input type='text' ng-model='newPerson' />
<button ng-click='addNew()'>Add</button>
</div>
angularjs,
var app = angular.module('MyTutorialApp',[]);
app.controller("MainController", function($scope){
$scope.thisIsAScopeProperty = 'template/index.html';
$scope.people = [
{
id: 0,
name: 'Leon',
music: [
'Rock',
'Metal',
'Dubstep',
'Electro'
],
live: true
}
];
$scope.newPerson = null;
$scope.addNew = function() {
alert(1); // works here when you click the Add button
console.log($scope.newPerson); // but returns nothing when you type any text in the input
if ($scope.newPerson != null && $scope.newPerson != "") {
alert(2); // does not work here
$scope.people.push({
id: $scope.people.length,
name: $scope.newPerson,
live: true,
music: [
'Pop',
'RnB',
'Hip Hop'
]
});
}
}
});
Any ideas why and how can I fix it?

Use
<input type='text' ng-model='$parent.newPerson' />
ng-include creates a new scope, and because newPerson is a simple property, it's a different one on the child and parent scopes (i.e. changing one doesn't change the other). So when the included template sets newPerson it's still null on the mainController's scope.
For a better understanding of how scopes work, read https://github.com/angular/angular.js/wiki/Understanding-Scopes

Related

AngularJS controller not returning value

new to AngularJS here, just started a new application, but it seems I'm missing something important in regards to controllers.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Arsenal Roster</title>
<link rel="stylesheet" href="bootstrap-3.3.7-dist/css/bootstrap.css" />
<script src="angular.min.js"></script>
</head>
<body>
<div ng-app="arsenalApp" ng-controller="ArsenalController">
<input ng-model="name">
<span>{{age}}</span>
</div>
<script>
var arsenalApp=angular.module('arsenalApp',[]);
arsenalApp.controller('ArsenalController',function($scope){
if($scope.name=="jon"){
$scope.age=12;
}else{
$scope.age=1;
}
});
</script>
</body>
</html>
The functionality I want is: if I input 'jon' in the textbox, the output in the browser should change to 12, otherwise, for any other text, it should remain as 1.
As of now it just outputs 1 and doesn't change on entering 'jon'. What am I missing about controllers?
<input ng-model="name" ng-change="onNameChange()">
$scope.onNameChange = function () {
if ($scope.name=="jon") {
$scope.age=12;
} else {
$scope.age=1;
}
}
You need to listen to the change event whenever the name is being changed and the change function should handle your conditions.

Form control with angular.js

I have been playing about with angular and forms but I am having some trouble with the code below. I thought that it should add forenames to the ones already displayed by the ng-repeat whenever the form is submitted but the submit button appears to do nothing.
HTML:
<!DOCTYPE html>
<html lang="en" ng-app="file">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
<script types="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script types=text/javascript" src="formLoops.js"></script>
<title>Title</title>
</head>
<body ng-controller="PersonalDetailsController as person">
<p ng-repeat="info in person.details">{{info.forename}}</p>
<form name="PersonalDetailsForm" ng-controller="DataEntryController as dataCtrl" ng-submit="addPerson(person)">
<blockquote>
<p>{{dataCtrl.person.forename}}</p>
<p>{{dataCtrl.person.surname}}</p>
</blockquote>
<label>Forename:</label>
<input ng-model="dataCtrl.person.forename"/>
<label>Surname:</label>
<input ng-model="dataCtrl.person.surname"/>
<input type="submit" value="submit"/>
</form>
</body>
</html>
JS:
var app = angular.module("file", []);
app.controller("PersonalDetailsController", function() {
this.details = personalDetails;
});
app.controller("DataEntryController", function() {
this.person = {};
this.addPerson = function(person) {
person.personalDetails.push(this.person);
};
});
var personalDetails = [{
forename: "John",
surname: "Doe"
},
{
forename: "John",
surname: "Smith"
}
];
You need to do two changes to the code
1) In HTML you need to add the ng-submit="dataCtrl.addPerson(person)"
since you are using the controller as syntax
2) You need to change your js code as follows person.personalDetails.push(this.person); to person.details.push(this.person);
This is because your repeat is working with the details array so you need to push the new data to the details array itself. You are trying to push the data inside the global array that is why it is not worked
Thanks
since you are using the controllerAs use the controllerAs reference when you are calling the function. like ng-submit="dataCtrl.addPerson(person)"
<form name="PersonalDetailsForm" ng-controller="DataEntryController as dataCtrl" ng-submit="dataCtrl.addPerson(person)">
You will need to find a way of sharing data between controllers.
One of the ways is using an angular service.
Check out this plunk!
https://plnkr.co/edit/oimKIgCDKknwsmSWbUsT?p=preview
script.js
var app = angular.module("file", []);
app.controller("PersonalDetailsController", function(PersonService) {
this.details = PersonService.personalDetails;
});
app.controller("DataEntryController", function(PersonService) {
this.person = {};
this.addPerson = function(person) {
PersonService.personalDetails.push(this.person);
};
});
app.service("PersonService", function() {
this.personalDetails = [{
forename: "John",
surname: "Doe"
}, {
forename: "John",
surname: "Smith"
}];
});
index.html
<!DOCTYPE html>
<html lang="en" ng-app="file">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
<script types="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script types="text/javascript " src="script.js"></script>
<title>Title</title>
</head>
<body ng-controller="PersonalDetailsController as person ">
<pre>
{{person | json}}
</pre>
<p ng-repeat="info in person.details ">{{info.forename}}</p>
<form name="PersonalDetailsForm " ng-controller="DataEntryController as dataCtrl " ng-submit="dataCtrl.addPerson(dataCtrl.person) ">
<pre>
{{dataCtrl.person | json}}
</pre>
<label>Forename:</label>
<input ng-model="dataCtrl.person.forename " />
<label>Surname:</label>
<input ng-model="dataCtrl.person.surname " />
<input type="submit " value="submit " />
</form>
</body>
</html>

ng-blur is not triggered when I lose focus

So i've been trying to be able to change the title of a playlist by double clicking on it.
I'm using ng-blur to know when i lose focus on the edit, but the doneEditing function is never called. (editTitle and done editing just set playlist.editing to true and false and console.log editing and done editing).
.html
<html>
<head>
<meta charset="UTF-8">
<title>Playlist</title>
<link rel="stylesheet" href="css/reset.css">
<link rel="stylesheet" href="css/style.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
</head>
<body>
<article ng-app>
<div class="todo-wrapper" ng-controller="TodoCtrl">
<h2 ng-hide="playlist.editing" ng-dblclick="editTitle(playlist)">{{playlist.title}}</h2>
<input ng-show="playlist.editing" ng-model="playlist.title" ng-blur="doneEditing(playlist)" autofocus />
<ul>
<li ng-repeat="todo in todos">
<input type="checkbox" ng-model="todo.done"/>
<span class="done-{{todo.done}}">{{todo.text}}</span>
</li>
</ul>
<form>
<input class="add-input" placeholder="I need to..." type="text" ng-model="formTodoText" />
<button class="add-btn" ng-click="addTodo()"><h2>Add</h2></button>
</form>
<button class="clear-btn" ng-click="clearCompleted()">Clear completed</button>
</div>
</article>
<script src="js/index.js"></script>
<script src='http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js'></script>
</body>
</html>
.js
function TodoCtrl($scope) {
$scope.todos = [
{text:'Movie1', done:false},
{text:'Movie2', done:false}
];
$scope.playlist = {title: "New Playlist", editing:false};
$scope.getTotalTodos = function () {
return $scope.todos.length;
};
$scope.addTodo = function () {
$scope.todos.push({text:$scope.formTodoText, done:false});
$scope.formTodoText = '';
};
$scope.clearCompleted = function () {
$scope.todos = _.filter($scope.todos, function(todo){
return !todo.done;
});
};
$scope.editTitle = function (playlist) {
playlist.editing = true;
};
$scope.doneEditing = function (playlist) {
playlist.editing = false;
};
}
I'm not sure what i'm doing wrong here, because the examples I've found on fiddle (http://jsfiddle.net/davekr/F7K63/43/) are working fine using those lines.
PS : I've tested to run the code on both Firefox and Chrome, the doneEditing function has never been called.
Edit : Uploaded the full .html and .js files
You need to add ng-model="playlist.title"to the input tag
<h2 ng-hide="playlist.editing" ng-click="editTitle(playlist)">{{playlist.title}}</h2>
<input ng-show="playlist.editing" ng-model="playlist.title" ng-blur="doneEditing(playlist)" autofocus />
And if you add console.log("foo"); to the doneEditing function you can see that it is working correctly
EDIT
Here is a plunker
https://plnkr.co/edit/LoW9nkhYO5BIaOzuaxOX?p=preview
Update AngularJS to newest version or at least 1.2 <

kendo ui on-demand RTL support with script

I created an Autocomplete form. I followed this simple documentation to create a button together with its click handler script. Clicking this button shall toggle RTL support for the form.
I have a problem. When I click the button, it does not toggle RTL support for the form.
demo
<body>
<input type="button" id="toggleRTL" value="Activate RTL Support" class="k-button" />
<script>
$('#toggleRTL').on('click', function(event) {
var form = $('#speakerForm');
if (form.hasClass('k-rtl')) {
form.removeClass('k-rtl')
} else {
form.addClass('k-rtl');
}
})
</script>
<input id="autocomplete" type="text" />
<script>
$("#autocomplete").kendoAutoComplete({
dataSource: {
data: [
{name: "Google"},
{name: "Bing"}
]
},
dataTextField: "name",
})
</script>
</body>
I think you missing some point from the tutorial :
you need to put all of your component to a container element and apply the k-rtl class to the container
you have a problem on your js where you dont have element with id speakerForm
UPDATE
3. as your comment i, i observe the behavior of the k-rtl and kendo autocomplete widget and the result is the suggestion will be still on the left side if we create the widget first then adding the k-rtl clas. So what do we need is the container having the k-rtl class first then initializing the widget.
4. i updated my code so that every time you click the button the #autocomplete div will be removed with its parent( result from kendo autocomplete which is a span) then append new element and re-initializing the kendo autocompelete widget
I think it's working if you follow it like this
function createAutoComplete(){
if($("#autocomplete").data("kendoAutoComplete") != null){
$("#autocomplete").parent().remove();
$("#container").append("<input id='autocomplete' type='text' />")
}
$("#autocomplete").kendoAutoComplete({
dataSource: {
data: [{
name: "Google"
}, {
name: "Bing"
}]
},
dataTextField: "name",
});
}
createAutoComplete();
$('#toggleRTL').on('click', function(event) {
var form = $('#container');
console.log(form);
if (form.hasClass('k-rtl')) {
console.log("test1");
form.removeClass('k-rtl')
} else {
console.log("test2");
form.addClass('k-rtl');
}
createAutoComplete();
})
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Untitled</title>
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.common.min.css">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.rtl.min.css">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.default.min.css">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.mobile.all.min.css">
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2015.3.930/js/angular.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2015.3.930/js/jszip.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2015.3.930/js/kendo.all.min.js"></script>
</head>
<body>
<div id="container">
<input type="button" id="toggleRTL" value="Activate RTL Support" class="k-button" />
<input id="autocomplete" type="text" />
</div>
</body>
</html>
I have updated your dojo.
http://dojo.telerik.com/AfeNi/4
But as #machun has stated you are missing some elements of the mechanics of this process.
I have added the missing form element speakerForm and then added some additional console.log() statements showing the actions being performed.
if you need any more info let me know.

Angularjs external templating: the template cannot be loaded?

I thought loading an external template with Angularjs is as simple as this below,
<div ng-include='template/index.php'></div>
But it does not print anything out on the browser. What have I missed?
The html,
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Angualr</title>
<meta charset="utf-8">
<script src="js/angular.min.js"></script>
<script src="js/app.js" type="text/javascript"></script>
<script src="js/maincontroller.js" type="text/javascript"></script>
</head>
<body>
<div ng-include='template/index.php'></div>
</body>
</html>
the template,
<div id='content' ng-app='MyTutorialApp' ng-controller='MainController'>
<input type='text' ng-model='searchText' />
<ul>
<li ng-repeat='person in people | filter:searchText' ng-show='person.live == true'>#{{person.id}} {{person.name}}</li>
</ul>
<input type='text' ng-model='newPerson' />
<button ng-click='addNew()'>Add</button>
</div>
js/app.js,
var app = angular.module('MyTutorialApp',[]);
js/maincontroller.js,
app.controller("MainController", function($scope){
$scope.people = [
{
id: 0,
name: 'Leon',
music: [
'Rock',
'Metal',
'Dubstep',
'Electro'
],
live: true
},
{
id: 1,
name: 'Chris',
music: [
'Indie',
'Drumstep',
'Dubstep',
'Electro'
],
live: true
}
];
$scope.newPerson = null;
$scope.addNew = function() {
if ($scope.newPerson != null && $scope.newPerson != "") {
$scope.people.push({
id: $scope.people.length,
name: $scope.newPerson,
live: true,
music: [
'Pop',
'RnB',
'Hip Hop'
]
});
}
}
});
EDIT:
Directories,
index.html
js/
...
...
template/
index.php
EDIT 2:
index.html,
<div ng-app='MyTutorialApp'>
<div ng-include='template/index.php'></div>
</div>
template/index.php,
<div id='content' ng-controller='MainController'>
<input type='text' ng-model='searchText' />
<ul>
<li ng-repeat='person in people | filter:searchText' ng-show='person.live == true'>#{{person.id}} {{person.name}}</li>
</ul>
<input type='text' ng-model='newPerson' />
<button ng-click='addNew()'>Add</button>
</div>
Live demo here (click).
ng-include looks for a $scope property, so you need to pass it a string, like this: ng-include="'/template/index.php'".
<div ng-include="'/template/index.php'"></div>
What you were passing to it essentially makes it look for this in your controller: $scope['/template/index.php'] = 'some string';
You're also bootstrapping angular in the template itself - so how could it be included? ng-app needs to be in the main page so that ng-include can work!
<some-element ng-app="myApp">
<!-- in here, angular things work (assuming you have created an app called "myApp" -->
<div ng-include="'/template/index.php'"></div>
</some-element>
Just replace some-element with something like html, body or whatever element you want the app to work from.
You bootstrapped your ng-app in the template, but you have to bootstrap it in your main page.
So just move the ng-app directive from the template to the main-page, e.G.
<html ng-app="MyTutorialApp">
<div ng-include src='template/index.php'></div>
try this
and add ng-app into top of the page
<html ng-app='MyTutorialApp'>
you must have bootstrap you angular application into your index.html

Categories

Resources