Dynamic Angular Js Not working via innerHTML - angularjs

If I add a row with Dynamic Angular JS variable, it is not working.
Below is my code. Please help me let know the issue.
Also please note that the inner HTML in my original code is 600 lines long. In this example I have used simple div to simplify.
<div data-ng-init="quantity_r=1;price_r=5">
<h2>Cost Calculator Quantity:</h2>
<input type="number" ng-model="quantity_r"> Price: <input type="number" ng-model="price_r">
<div>
Total in dollar: {{quantity_r * price_r}}
</div>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<script>
var app = angular.module('myApp', []);
app.controller('AppCtrl', function($scope) {
});
</script>
<script>
var app = angular.module('myApp1', []);
app.controller('AppCtrl', function($scope) {
angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) {
$scope.a = 1;
$scope.b = 2;
});
});
function replicateRegion() {
var table = document.getElementById("idTable");
var lastRow = table.rows.length;
var row = table.insertRow(lastRow);
var cell1 = row.insertCell(0);
var sHTML =document.getElementById("idTableTD1").innerHTML;
sHTML=sHTML.replace("_r", "_r" + lastRow.toString());
sHTML=sHTML.replace("Cost Calculator Quantity:", "Cost Calculator Quantity: Row Added " + lastRow.toString());
cell1.innerHTML = sHTML;
}
</script>
<div id="id1" ng-app="myApp" ng-controller="AppCtrl">
<button onclick="replicateRegion()">insert Row</button>
<table id="idTable">
<tr><td id="idTableTD1">
<div data-ng-init="quantity_r=1;price_r=5">
<h2>Cost Calculator Quantity:</h2>
<input type="number" ng-model="quantity_r"> Price: <input type="number" ng-model="price_r">
<div>
Total in dollar: {{quantity_r * price_r}}
</div>
</td></tr>
</table>
</div>
</body>
</html>
Only the first row which is static has the correct output. The rows added after button-click "Insert Row" have the problematic Angular JS output. Please help.

You need to add the code for replicateRegion() function inside the AngularJS controller and use the $compile service to bind the dynamically generated HTML into the AngularJS DOM.
var myapp = angular.module('myApp', []);
myapp.controller('AppCtrl', function ($compile, $scope) {
$scope.a = 1;
$scope.b = 2;
$scope.replicateRegion = function(){
var table = document.getElementById("idTable");
var lastRow = table.rows.length;
var row = table.insertRow(lastRow);
var template = `<div data-ng-init="quantity_r=1;price_r=5">
<h2>Cost Calculator Quantity:</h2>
<input type="number" ng-model="quantity_r"> Price: <input type="number" ng-model="price_r">
<div>
Total in dollar: {{quantity_r * price_r}}
</div>
</div>`;
var cell1 = row.insertCell(0);
template=template.replace(/_r/g, "_r" + lastRow.toString());
template=template.replace("Cost Calculator Quantity:", "Cost Calculator Quantity: Row Added " + lastRow.toString());
cell1.innerHTML = template;
$compile(cell1)($scope); //Now compile it to render the directive.
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div id="id1" ng-app="myApp" ng-controller="AppCtrl">
<button ng-click="replicateRegion()">insert Row</button>
<table id="idTable">
<tr><td id="idTableTD1">
<div data-ng-init="quantity_r=1;price_r=5">
<h2>Cost Calculator Quantity:</h2>
<input type="number" ng-model="quantity_r"> Price: <input type="number" ng-model="price_r">
<div>
Total in dollar: {{quantity_r * price_r}}
</div>
</div>
</td></tr>
</table>
</div>
Also notice that var template that specifies a generic template that should be inserted in the HTML dynamically on click. It is always a good practice to specify a static HTML template instead of extracting the generated HTML from the page and using that, which you have done.

When you add markup manually, like
document.getElementById('idTableTD1').innerHTML= '<div dynamic></div>'
you are bypassing all AngularJS code. You should do it rather as this:
angular.element("#idTableTD1").html('<div dynamic></div>');
may be this will help.

Related

Append chosen image to div tag and display one by one using ng-repeat in onclick button Angular JS

How to append choose images one by one to div tag using using ng-repeat when I click Add button after chosen file <input type="file"> in Angular JS. I have tried code below:
<body ng-app="myApp">
<div ng-controller="mainController">
<div>
<h3>Added Images: {{addedImages()}}</h3>
</div>
<div>
<input type="file" id="filename" ng-model="filename" name="">
<button ng-click="test()">Add Image</button>
<div class="shelfgallery"></div>
</div>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('mainController', function($scope) {
$scope.imageSources=[];
$scope.test = function(){
var url = ""//facing trouble in getting full URL of choosen image
alert(url);
$scope.imageSources.push({
imges: $scope.filename
});
var element = angular.element($('.shelfgallery'));
element.append('<img id="img_11" ng-repeat="imageSource in imageSources track by $index" ng-src="{{imageSource }}" /><br><br>');
//$compile(element)($scope);
};
$scope.addedImages = function(){
return $scope.imageSources.length;
}
});
</script>
</body>
If any wrong here let me know, or any other solution.

Adding ng-model directive to dynamically created input tag using AngularJs

I am trying that on a button click, a div and and input tag are created and the input tag contain ng-model and the div has binding with that input.
Kindly suggest some solution.
You can create the div and input beforehand and and do not show it by using ng-if="myVar". On click make the ng-if="true".
<button ng-click="myVar = true">
In controller : $scope.myVar = false;
$scope.addInputBox = function(){
//#myForm id of your form or container boxenter code here
$('#myForm').append('<div><input type="text" name="myfieldname" value="myvalue" ng-model="model-name" /></div>');
}
Here is another solution, in which there's no need to create a div and an input explicitly. Loop through an array of elements with ng-repeat. The advantage is that you will have all the values of the inputs in that array.
angular.module('app', [])
.controller('AppController', AppController);
AppController.$inject = ['$scope'];
function AppController($scope) {
$scope.values = [];
$scope.add = function() {
$scope.values.push('');
};
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="AppController">
<button ng-click="add()">Click</button>
<div ng-repeat="value in values track by $index">
<input type="text" ng-model="values[$index]"/>
<div>{{values[$index]}}</div>
</div>
<pre>{{values}}</pre>
</div>
UPDATE. And if you want only one input, it's even simpler, using ng-show.
angular.module('app', []);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<button ng-click="show = true">Click</button>
<div ng-show="show">
<input type="text" ng-model="value"/>
<div>{{value}}</div>
</div>
</div>
You should use $compile service to link scope and your template together:
angular.module('myApp', [])
.controller('MyCtrl', ['$scope', '$compile', '$document' , function MyCtrl($scope, $compile, $document) {
var ctrl = this;
var inputTemplate = '<div><span ng-bind="$ctrl.testModel"></span>--<span>{{$ctrl.testModel}}</span><input type="text" name="testModel"/></div>';
ctrl.addControllDynamically = addControllDynamically;
var id = 0;
function addControllDynamically() {
var name = "testModel_" + id;
var cloned = angular.element(inputTemplate.replace(/testModel/g, name)).clone();
cloned.find('input').attr("ng-model", "$ctrl." + name); //add ng-model attribute
$document.find('[ng-app]').append($compile(cloned)($scope)); //compile and append
id++;
}
return ctrl;
}]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.angularjs.org/1.6.2/angular.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl as $ctrl">
<input type="button" value="Add control dynamically" ng-click="$ctrl.addControllDynamically()"/>
</div>
</div>
UPDATE: to add a new compiled template each time the button is clicked, we need to make a clone of the element.
UPDATE 2: The example above represents a dirty-way of manipulating the DOM from controller, which should be avoided. A better (angular-)way to solve the problem - is to create a directive with custom template and use it together with ng-repeat like this:
angular.module('myApp', [])
.controller('MyCtrl', ['$scope', function MyCtrl($scope) {
var ctrl = this;
ctrl.controls = [];
ctrl.addControllDynamically = addControllDynamically;
ctrl.removeControl = removeControl;
function addControllDynamically() {
//adding control to controls array
ctrl.controls.push({ type: 'text' });
}
function removeControl(i) {
//removing controls from array
ctrl.controls.splice(i, 1);
}
return ctrl;
}])
.directive('controlTemplate', [function () {
var controlTemplate = {
restrict: 'E',
scope: {
type: '<',
ngModel: '='
},
template: "<div>" +
"<div><span ng-bind='ngModel'></span><input type='type' ng-model='ngModel'/></div>" +
"</div>"
}
return controlTemplate;
}]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.angularjs.org/1.6.2/angular.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl as $ctrl">
<input type="button" value="Add control dynamically" ng-click="$ctrl.addControllDynamically()"/>
<div ng-repeat="control in $ctrl.controls">
<control-template type="control.type" ng-model="control.value"></control-template>
</div>
</div>
</div>

AngularJs can't run a method

I am a beginner angularjs user, but i have to learn it for my new job and I thought I could practice a bit. So I did a simple string reverse method and I thought I could make a simple calculator (exactly, only sum). Here is my code. I made 2 modules, 2 controllers and the first one is working fine, but the calculator isn't. However I made a simple site, where only the calc code is, and it works fine and I don't understand why it works, but doesn't work if 2 modules are on the same site.(Yeah, i'm a very beginner). Thank you for your help.
<!DOCTYPE html>
<html lang="en">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"> </script>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div ng-app="MyApp" ng-controller="myController">
<center>
<input type="text" ng-model="myString" placeholder="Enter text"/>
<p>Input: {{myString }}</p>
<p>Filtered input: {{getReverse()}}</p>
</center>
</div>
<br><br>
<center>
<div ng-app="MyCalc" ng-controller="myCalculate">
<input type="text" ng-model="firstNumber"><br>
<input type="text" ng-model="secondNumber"><br>
<p> Result: {{getResult()}}</p>
</div>
</center>
<script>
var reverse = angular.module("MyApp", []);
var calc = angular.module("MyCalc",[]);
reverse.controller('myController',function($scope){
$scope.myString = "";
$scope.getReverse = function(){
return $scope.myString.split("").reverse().join("");
}
});
calc.controller('myCalculate',function($scope){
$scope.firstNumber = 0;
$scope.secondNumber = 0;
$scope.getResult = function(){
return Number($scope.firstNumber)+Number($scope.secondNumber);
}
});
</script>
ng-app directive can be used just one time in page.
only one AngularJS application can be auto-bootstrapped per HTML document. The first ngApp found in the document will be used to define the root element to auto-bootstrap as an application. To run multiple applications in an HTML document you must manually bootstrap them using angular.bootstrap instead. (https://docs.angularjs.org/api/ng/directive/ngApp)
But you can bootstrap manually your app. Affect id on div that contains an angular app and add this to your script (https://plnkr.co/edit/ZTW7mXx3iXm803xdYod1?p=preview):
angular.bootstrap(document.getElementById('reverse'), ['MyApp']);
angular.bootstrap(document.getElementById('calc'), ['MyCalc']);
But I agree with Vikash, create more modules and less app :)
Normally, you should not use 2 angular app in a web page.
If you need to use different module, just make one depend on another.
Let's say your main module is MyApp and you need MyCalc's function, you do it like this (JsFiddle):
var calc = angular.module("MyCalc",[]);
calc.controller('myCalculate',function($scope){
$scope.firstNumber = 0;
$scope.secondNumber = 0;
$scope.getResult = function(){
return Number($scope.firstNumber)+Number($scope.secondNumber);
}
});
// Make MyApp module depend on MyCalc
var reverse = angular.module("MyApp", ["MyCalc"]);
reverse.controller('myController',function($scope){
$scope.myString = "";
$scope.getReverse = function(){
return $scope.myString.split("").reverse().join("");
}
});
And then in the HTML:
<body ng-app="MyApp">
<div ng-controller="myController">
<center>
<input type="text" ng-model="myString" placeholder="Enter text"/>
<p>Input: {{myString }}</p>
<p>Filtered input: {{getReverse()}}</p>
</center>
</div>
<br><br>
<center>
<div ng-controller="myCalculate">
<input type="text" ng-model="firstNumber"><br>
<input type="text" ng-model="secondNumber"><br>
<p> Result: {{getResult()}}</p>
</div>
</center>
</body>
P/s: If you really need to bootstrap 2 angular app in the same web page, you need to bootstrap it manually (JsFiddle):
angular.bootstrap(document.getElementById('calc'), ['MyCalc']);
calc is the id of the element you need to bootstrap the second app on
<div id="calc" ng-controller="myCalculate">
use ng-module instead of ng-app because ng-app can be used with one module in one page.
<div ng-module="MyModuleA">
<h1>Module A</h1>
<div ng-controller="MyControllerA">
{{name}}
</div>
<div ng-module="MyModuleB">
<h1>Just Module B</h1>
<div ng-controller="MyControllerB">
{{name}}
</div>
var moduleA = angular.module("MyModuleA", []);
moduleA.controller("MyControllerA", function($scope) {
$scope.name = "Bob A";
});
var moduleB = angular.module("MyModuleB", []);
moduleB.controller("MyControllerB", function($scope) {
$scope.name = "Steve B";
});
Use angular ng-modules to achieve this
here is the working [link] [1]
[1] http://jsfiddle.net/j5jzsppv/111/
<div ng-modules="MyModuleA, MyModuleB">
<div ng-controller="myController">
<input type="text" ng-model="myString" placeholder="Enter text"/>
{{myString}}
<p>Filtered input: {{getReverse()}}</p>
</div>
<div ng-controller="myCalculate">
<input type="text" ng-model="firstNumber"><br>
<input type="text" ng-model="secondNumber"><br>
<p> Result: {{getResult()}}</p>
</div>
var reverse = angular.module("MyModuleA", []);
var calc = angular.module("MyModuleB", []);
reverse.controller('myController', function ($scope) {
$scope.myString = "";
$scope.getReverse = function () {
return $scope.myString.split("")
.reverse()
.join("");
}
});
calc.controller('myCalculate', function ($scope) {
$scope.firstNumber = 0;
$scope.secondNumber = 0;
$scope.getResult = function () {
return Number($scope.firstNumber) + Number($scope.secondNumber);
}
});

Angular JS: After Adding controller in external file doesn't give the expected result

I am trying to call a external js file to implement angular js controller. Please find the code below. But it is not giving the result for the external js file access code is being added. Could someone correct me what am i doing mistake here?
[It gives the proper result if I don't have added the external js access code]
<!DOCTYPE html>
<html >
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"> </script>
<body ng-app="myApp">
<!-- Angular JS controller sample -->
<div ng-controller="myAppCtrl">
First name : <input type="text" ng-model="firstName"> <br>
Last name : <input type="text" ng-model="lastName"> <br>
Full name is : {{firstName + " " + lastName}} <br>
</div>
<script>
var app = angular.module('myApp',[]);
app.controller('myAppCtrl', function($scope) {
$scope.firstName = "Prabakar"
$scope.lastName = "Prabu"
});
</script>
<!-- Method based controller -->
<div ng-controller="methodCtrler">
<br>
First name is : <input type="text" ng-model="fName"> <br>
Last name is : <input type="text" ng-model="lName"> <br>
Full name : {{myFunction() }}
<br>
</div>
<script>
//var app1 = angular.module('myApp',[]);
app.controller ('methodCtrler', function($scope) {
$scope.fName = "Jonathan"
$scope.lName = "Gladwin"
$scope.myFunction = function() {
return $scope.fName + " " + $scope.lName;
}
});
</script>
<!-- Method call from external JS files -->
<br>
<div ng-controller ="ryanContrler">
My first name : <input type="text" ng-model="ryanFirstname"> <br>
My last name : <input type="text" ng-model="austinLastname"> <br>
My full name : {{fullName()}
</div>
<script src ="ryanNameContorller.js"></script>
</body>
</html>
ryanNameContorller.js
angular.module ('myApp', []).controller('ryanContrler', function($scope) {
$scope.ryanFirstname = "Ryan",
$scope.austinLastname = "Austin",
$scope.fullName = function () {
return $scope.ryanFirstname + " " + $scope.austinLastname;
}
});
And the result is,
You missed } in ryanContrler replace My full name : {{fullName()} with My full name : {{fullName()}}
Use this new code in ryanNameContorller.js file
angular.module('myApp').controller('ryanContrler', ['$scope', function($scope){
$scope.ryanFirstname = "Ryan",
$scope.austinLastname = "Austin",
$scope.fullName = function() {
return $scope.ryanFirstname + " " + $scope.austinLastname;
}
}]);
HTML
<!DOCTYPE html>
<html >
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"> </script>
<body ng-app="myApp">
<!-- Angular JS controller sample -->
<div ng-controller="myAppCtrl">
First name : <input type="text" ng-model="firstName"> <br>
Last name : <input type="text" ng-model="lastName"> <br>
Full name is : {{firstName + " " + lastName}} <br>
</div>
<script>
var app = angular.module('myApp',[]);
app.controller('myAppCtrl', function($scope) {
$scope.firstName = "Prabakar"
$scope.lastName = "Prabu"
});
</script>
<!-- Method based controller -->
<div ng-controller="methodCtrler">
<br>
First name is : <input type="text" ng-model="fName"> <br>
Last name is : <input type="text" ng-model="lName"> <br>
Full name : {{myFunction() }}
<br>
</div>
<script>
//var app1 = angular.module('myApp',[]);
app.controller ('methodCtrler', function($scope) {
$scope.fName = "Jonathan"
$scope.lName = "Gladwin"
$scope.myFunction = function() {
return $scope.fName + " " + $scope.lName;
}
});
</script>
<!-- Method call from external JS files -->
<br>
<div ng-controller ="ryanContrler">
My first name : <input type="text" ng-model="ryanFirstname"> <br>
My last name : <input type="text" ng-model="austinLastname"> <br>
My full name : {{fullName()}}
</div>
<script src ="ryanNameContorller.js"></script>
</body>
</html>
Demo here
There are a couple mistakes in the code that might or might not contributed to the cause.
You should spell Controller correctly. Ctrl/Ctrler/Contorller are just confusing yourself and whoever that needs to maintain your code.
angular.module('myApp',[]) should only be called once. If you need to get the app in external js file, use angular.module('myApp').
Put scripts inside <head> or <body>, don't put it in <html> directly.
You should check console log first when you encounter error. If you don't understand it, post it in the question. (Hint: press F12 to open)
The problem is your <script> to add js file is after ng-controller <div> put it inside your <head> to make sure that it call first
Your HTML:->
<html >
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"> </script>
<script src ="ryanNameContorller.js"></script>
</head>
<body ng-app="myApp">
<!-- Angular JS controller sample -->
<div ng-controller="myAppCtrl">
First name : <input type="text" ng-model="firstName"> <br>
Last name : <input type="text" ng-model="lastName"> <br>
Full name is : {{firstName + " " + lastName}} <br>
</div>
<script>
var app = angular.module('myApp',[]);
app.controller('myAppCtrl', function($scope) {
$scope.firstName = "Prabakar"
$scope.lastName = "Prabu"
});
</script>
<!-- Method based controller -->
<div ng-controller="methodCtrler">
<br>
First name is : <input type="text" ng-model="fName"> <br>
Last name is : <input type="text" ng-model="lName"> <br>
Full name : {{myFunction() }}
<br>
</div>
<script>
//var app1 = angular.module('myApp',[]);
app.controller ('methodCtrler', function($scope) {
$scope.fName = "Jonathan"
$scope.lName = "Gladwin"
$scope.myFunction = function() {
return $scope.fName + " " + $scope.lName;
}
});
</script>
<!-- Method call from external JS files -->
<br>
<div ng-controller ="ryanContrler">
My first name : <input type="text" ng-model="ryanFirstname"> <br>
My last name : <input type="text" ng-model="austinLastname"> <br>
My full name : {{fullName()}}
</div>
</body>
</html>

How to dynamically create text box when we click on a link using angularjs

I have a problem to show INPUT field when do some action.
I have BUTTON (Click here) as soon as user made a click event on button i wanted to show input field
I have done this by using jQuery.
Can any one help me in Angular.js
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.boxShow = false;
});
</script>
<div ng-app="myApp">
<div ng-controller="myCtrl">
show box
<div ng-show="boxShow">
<textarea rows="4" cols="50">text</textarea>
</div>
</div>
</div>
https://jsfiddle.net/bxwjpmaa/1/
HTML
<div class="btn btn-primary" ng-click="openTextBox();">Click Me To open text box</div>
<div ng-show="openTextBox == true">
<input type="text"/>
</div>
SCRIPT :
$scope.openTextBox = function () {
$scope.openTextBox = true;
}
please don't take scope variables and function names same
example here
$scope.openTextBox = function () {
$scope.openTextBox = true;
}
//this is not correct as per angular documentation because scope.openTextBox name already assigned to scope function,again its assigning scope variable "$scope.openTextBox = true" here u will get errors when ever u clicked div second time" TypeError: boolean is not a function" it will throw this error.so please dont use which is already assigned scope function dont assign scope variable
see this fiddle url : https://jsfiddle.net/veerendrakumarfiddle/bxwjpmaa/2/
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<ol>
<li ng-repeat="element in elements">
<input type="text" ng-model="element.value"/>
</li>
</ol>
<br/>
<b>Click here to add Textbox:</b><br/><input type="button" value="New Item" ng-click="newItem()"/>
<br/>
<br/>
<b>Click here to see ng-model value:</b><br/>
<input type="button" value="submit" ng-click="show(elements)">
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
var counter=0;
$scope.elements = [ {id:counter, value : ''} ];
$scope.newItem = function(){
counter++;
$scope.elements.push( { id:counter,value:''} );
}
$scope.show=function(elements)
{
alert(JSON.stringify(elements));
}
});
</script>
</body>
</html>

Resources