I have an AngularJS app that I manually bootstrap at time 't'. At time 't + 1', I would like to show an HTML element that has no ng-controller attached. I would like to dynamically add a ng-controller to this element so it can communicate with my javascript code.
How can I do that?
PS I tried to dynamically add the ng-controller attribute to the element but it doesn't work.
To do that you need to compile elements.
HTML
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.5/angular.min.js"></script>
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<link href="main.css" rel="stylesheet" type="text/css" />
<script src="main.js"></script>
<meta charset=utf-8 />
<title>Angular JS</title>
</head>
<body ng-controller="parentCtrl">
<button ng-click="setCtrl2()">Set Controller</button>
<div id="placeholder">
<span></span>
<select>
<option></option>
</select>
<span class="input-append">
<input id="add" type="text" placeholder="Another one ?" ng-model="addName" />
<input type="submit" class="btn btn-primary" ng-click="addRow()" value="+ add" />
</span>
</div>
</body>
</html>
Javascript
angular.module('app', []);
angular.module('app').controller('ctrl', function($scope) {
$scope.rows = ['Paul','John','Lucie'];
$scope.name = 'Jack';
$scope.addRow = function(){
$scope.rows.push($scope.addName);
$scope.addName = "";
console.log($scope.rows);
};
})
.controller('parentCtrl', function($scope) {
$scope.setCtrl2 = setCtrl;
});
function setCtrl() {
var elem = document.getElementById('placeholder');
elem.setAttribute('ng-controller', 'ctrl');
var eSpan = elem.children[0];
var eSelect = elem.children[1].children[0];
eSpan.setAttribute('ng-bind', 'name');
eSelect.setAttribute('ng-repeat', 'row in rows');
eSelect.setAttribute('value', '{{ row }}');
eSelect.setAttribute('ng-bind', 'row');
var injector = angular.element(elem).injector();
var compile = injector.get('$compile');
var rootScope = injector.get('$rootScope');
var result = compile(elem)(rootScope);
// When outside of AngularJS you need to call digest
// rootScope.$digest();
}
See: http://codepen.io/skarllot/pen/LVKpgd
You don't mention whether you've looked at previously asked questions. I found two which look like they could address the question you've asked:
Loading an AngularJS controller dynamically
How to bind an AngularJS controller to dynamically added HTML?
Related
Ive been trying for the past couple of hours but for I can't seem to figure out why I can access $scope.FeatureGroup to add to my url
Any ideas?
angular.module('ngRepeat', ['ngAnimate',]).controller('repeatController', function($scope, $http) {
$scope;
$scope.FeatureGroup = 50000;
$scope.ShowMeData = function($scope){
var url = 'URLHERE' + $scope.FeatureGroup;
$http.get(url).success(function(data) {
console.log(data);
//$scope.Object = data;
});
}
});
<html lang="en"><head>
<meta charset="UTF-8">
<title>Example - example-ng-repeat-production</title>
<link href="animations.css" rel="stylesheet" type="text/css">
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular-animate.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="ngRepeat">
<div ng-controller="repeatController">
There are Features - Please click them to see the page:
<br><input type="number" ng-model="FeatureGroup" ng-value="10" ng-keyup="ShowMeData()">
<br><input type="search" ng-model="q" placeholder="filter Features..." aria-label="filter friends">
<ul class="example-animate-container">
{{FeatureGroup}}
<!-- ngIf: Objects.length === 0 -->
<!-- ngRepeat: feature in Object | filter:q as results -->
</ul>
</div>
</body>
</html>
That is because of following line. You are overriding the $scope variable:
$scope.ShowMeData = function($scope){
You are really not passing any scope variable while calling the function
ng-keyup="ShowMeData()".
Just change it to:
$scope.ShowMeData = function(){
and it should work.
how to pass scope variable as 'FormName' of ng-click parameter to get FormName.$valid and FormName.$dirty in view angularjs.
Example:
var myApp = angular.module('myApp', []);
myApp.controller('Main', ['$scope',function($scope){
$scope.FormName = 'FormNameValidation';
$scope.showFormValidation = function(statusValid, statusDirty)
{
$scope.FormNameValidationStatus = statusValid;
$scope.FormNameDirtyStatus = statusDirty;
}
}]);
<form name="FormName" novalidate>
<div ng-app='myApp' ng-controller="Main">
<button type="button" ng-click="showFormValidation(FormName.$valid, FormName.$dirty)">Click</button>
{{FormNameValidationStatus}}
{{FormNameDirtyStatus}}
</div>
</form>
Output: undefined undefined
The problem is that the form element is not enclosed within the element that defines ngApp directive. If you rearrange the elements so that the form is a descendant of the div with the ng-app attribute you should get what you want
var myApp = angular.module('myApp', []);
myApp.controller('Main', ['$scope',
function($scope) {
$scope.FormName = 'FormNameValidation';
$scope.showFormValidation = function(statusValid, statusDirty) {
$scope.FormNameValidationStatus = statusValid;
$scope.FormNameDirtyStatus = statusDirty;
}
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<h1>Form State</h1>
<div ng-app="myApp" ng-controller="Main">
<form name="FormName" novalidate="">
<button type="button" ng-click="showFormValidation(FormName.$valid, FormName.$dirty)">Click</button>
{{FormNameValidationStatus}} {{FormNameDirtyStatus}}
</form>
</div>
</body>
</html>
I wrote a simple first app in AngularJS starting from a template for a todo list. None of the functions defined binds the scope (Both adding a new task or edit the current once). Anything I am doing commonly wrong in all the scopes of the controller?
Thanks in advance.
Here is my HTML:
<!DOCTYPE html>
<html>
<head>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0-beta.8/angular.js"></script>
<script src="js/script.js"></script>
<link href='//fonts.googleapis.com/css?family=Roboto:100,300' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="css/style.css" />
</head>
<body>
<div class="page-container">
<h2>Todo</h2>
<ul class="todo-list" ng-repeat="todo in todos track by $index">
<li>
<span>{{ todo }}</span>
<button class="bt bt-achieve" ng-click="done(todo)">Done</button>
</li>
</ul>
</div>
<ul class="add-todo">
<li>
<input type="text" class="txt" placeholder="New Todo" ng-model="newTodo" ng-keyup="add($event)" />
</li>
</ul>
</body>
</html>
And my JS Script:
var app = angular.module('Todo', []);
app.controller('TodoCtrl', function($scope) {
$scope.newTodo = '';
$scope.todos = [
'Maged Task',
'Essam Task',
'Ashraf Task'
];
$scope.done = function(todo) {
var indexOf = $scope.todos.indexOf(todo);
if (indexOf !== -1) {
$scope.todos.splice(indexOf, 1);
}
};
$scope.add = function(e) {
if (e.which && e.which === 13) {
$scope.todos.push($scope.newTodo);
$scope.newTodo = '';
}
};
});
you haven't bound to the angular app or controller.
Try
<body ng-app="ToDo" ng-controller="TodoCtrl">
Change the body tag as below
<body ng-app="Todo" ng-controller="TodoCtrl" >
I always prefer to give initial data in ng-init method .
In your code you can use the initial data for $scope.todos like as below.
html code :
<body ng-app="Todo" ng-controller="TodoCtrl" ng-init="initialData()" >
javascript code
Inside controller
$scope.initialData = function(){
$scope.newTodo = '';
$scope.todos = [
'Maged Task',
'Essam Task',
'Ashraf Task'
];
}
change <body> to <body ng-app="Todo" ng-controller=TodoCtrl>
I have a simple two-way binding setup with angular, and I added a plain javascript function that updates the value based off of the "alt" tag of an image a user clicks on. The problem is that when I hit save, the data doesn't update until I click inside the textbox and add a space. What's the best way to get around this?
http://plnkr.co/edit/j6tPYYUqvRyvfs32mcrW?p=preview
angular.module('copyExample', [])
.controller('ExampleController', ['$scope',
function($scope) {
$scope.master = {};
$scope.update = function(user) {
// Example with 1 argument
$scope.master = angular.copy(user);
};
$scope.reset = function() {
// Example with 2 arguments
angular.copy($scope.master, $scope.user);
};
$scope.reset();
}
]);
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
</head>
<body ng-app="copyExample">
<div ng-controller="ExampleController">
<form novalidate class="simple-form">
Name:
<input type="text" ng-model="user.name" id="name" />
<br />
<img src="http://placehold.it/100&text=John" onclick="changeText(alt)" alt="John" />
<br />
<button ng-click="reset()">RESET</button>
<button ng-click="update(user)">SAVE</button>
</form>
<pre>form = {{user | json}}</pre>
<pre>master = {{master | json}}</pre>
</div>
<script>
function changeText(value) {
document.getElementById('name').value = value
}
</script>
</body>
</html>
working fiddle - http://jsfiddle.net/lwalden/b2p7pu7g/
If you are already using Angular then don't write a plain vanilla javascript function for the image click event - use Angular.
Also it's recommended not to use the alt attribute in this way. You could use a data- attribute instead.
Additional attributes within a tag to pass values to a function
I'm learning how to develop with AngularJS for the first time for a class and I am trying to understand why I'm not getting an updated value of the length property and was hoping someone could help me understand why my code is not working and what I should be doing for it to update.
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<title>Grocery List</title>
<script src="js/angular.min.js"></script>
<script src="js/app.js"></script>
</head>
<body ng-app>
<h1>My Grocery List</h1>
<div ng-controller="MYController">
<input type="text" ng-model="listItem" placeholder="Add Grocery Item" />
<input type="submit" ng-click="addItem()" value="Save" />
<h2>Items</h2>
<ul ng-show="itemArray.length">
<li ng-repeat="listItem in itemArray">
{{ listItem }}
<buton ng-click="deleteItem(listItem)">X</buton>
</li>
</ul>
</div>
</body>
</html>
Code in app.js
function MYController($scope) {
$scope.listItem;
$scope.itemArray = [];
$scope.addItem = function() {
$scope.itemArray.push($scope.listItem);
$scope.listItem = '';
}
$scope.deleteItem = function(deletedItem) {
var idx = $scope.itemArray.indexOf(deletedItem);
$scope.itemArray.splice(idx, 1);
}
}
In Angular when you make controller then it need to assign with a module
So here you will made your controller in js like below
angular.module('todoApp', [])
.controller('MYController', ['$scope', function($scope) {
$scope.listItem;
$scope.itemArray = [];
$scope.addItem = function() {
$scope.itemArray.push($scope.listItem);
$scope.listItem = '';
}
$scope.deleteItem = function(deletedItem) {
var idx = $scope.itemArray.indexOf(deletedItem);
$scope.itemArray.splice(idx, 1);
}
});
And in HTML bootstrap angular like below in body tag and use your controller
<body ng-app="todoApp">
See here for reference https://angularjs.org/#add-some-control
I think there may be some confusion between the listItem in ng-model="listItem" and ng-repeat="listItem in itemArray". Try changing the second one to a different variable name like this:
<li ng-repeat="item in itemArray">
{{ item }}
<button ng-click="deleteItem(item)">X</button>
</li>
Also, change that first line in your controller $scope.listItem; to $scope.listItem = '';.
assign module to angular app using this code:
var app = angular.module('plunker', [])
and
<html ng-app="plunker">
see plunker