Binding not working in Angular Tutorial example - angularjs

<div ng-app="">
<input type="text" ng-model="data.message">
<h1>{{ data.message }}</h1>
<div ng-controller="FirstCtrl">
<input type="text" ng-model="data.message">
<h1>{{ data.message }}</h1>
</div>
<div ng-controller="SecondCtrl">
<input type="text" ng-model="data.message">
<h1>{{ data.message }}</h1>
</div>
</div>
This is the HTML code they had to demonstrate "Sharing Data Between Controllers" but the bindings inside FirstCtrl and SecondCtrl didn't work for me. Is this way of binding not included in Angular 1.3?
Controllers
function FirstCtrl($scope) {
}
function SecondCtrl($scope) {
}
Original Tutorial Link
Fiddle

As of angular 1.3 you can no longer use global functions as controllers, you must explicitly add them to your module.
Name your module in your markup ng-app="my-app"
Create a module in code var app = angular.module('my-app', []);
Add your controllers to the module app.controller('FirstCtrl', FirstCtrl)
Enjoy data binding

Related

Multiple "instances" of the same partial template in AngularJS

I have an AngularJS app that displays several plots. Each plot has a set of date controls to allow the user to change the start and end dates of the plotted data range. The date controls are loaded as a partial template in a uib-popover.
I've been using separate partial templates for each plot. I include the template in the page between <script type="text/ng-template"></script> tags, and load it using <button uib-popover-template="foo">Controls</button>.
This works fine, but having separate templates for each plot seems very repetitive, especially since I have several plots on the page. I tried creating a single template, setting the name of the plot for that "instance" of the template using ng-init, and hoping that would allow me to dynamically load the plot values into the template for that particular plot. Something along the lines of this:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.plots = {
"goodPlot": {
"start": "1/1/2018",
"end": "1/1/2019"
},
"betterPlot": {
"start": "5/5/2018",
"end": "3/10/2019"
}
};
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<div ng-app="myApp" ng-controller="myCtrl">
<h4>First Plot</h4>
<div ng-init="thisPlot = plots.goodPlot" ng-include="'plotControls.tmpl'"></div>
<hr/>
<h4>Second Plot</h4>
<div ng-init="thisPlot = plots.betterPlot" ng-include="'plotControls.tmpl'"></div>
<script type="text/ng-template" id="plotControls.tmpl">
<div class="form-group">
<label class="control-label">Start Date</label>
<input type="text" class="form-control" ng-model="thisPlot['start']">
</div>
<div class="form-group">
<label class="control-label">End Date</label>
<input type="text" class="form-control" ng-model="thisPlot['end']">
</div>
</script>
</div>
But as you can see, the start/end dates for both plots are the same. I understand why this is -- they're both binding to the same variables. But I can't figure out a solution to achieve the desired result.
Basically, I'm looking to create multiple "instances" of the same template, but with different variable values to be set before the ng-include.
Can anyone offer any suggestions?
Use a component to instantiate the template:
app.component("myPlotControls", {
bindings: { "plot", "<" },
templateUrl: "plotControls.tmpl",
})
Usage:
<my-plot-controls plot="plots.goodPlot"></my-plot-controls>
<my-plot-controls plot="plots.betterPlot"></my-plot-controls>
<script type="text/ng-template" id="plotControls.tmpl">
<div class="form-group">
<label class="control-label">Start Date</label>
<input type="text" class="form-control" ng-model="$ctrl.plot['start']">
</div>
<div class="form-group">
<label class="control-label">End Date</label>
<input type="text" class="form-control" ng-model="$ctrl.plot['end']">
</div>
</script>
Components create an isolate scope so that multiple instantiations of the same template will not conflict in the parent scope.
For more information, see
AngularJS Developer Guide - Creating Custom Components

post data inside clone div angularjs ng-model

Clone div is repeating, when I click add button.
How can I post the fields inside clone div.
<div class="row" id="append-row">
<div class="clone-div-{{count}}" id="clone-div">
<div class="col-md-6">
<div class="form-group input-group-sm">
<label>Title</label>
<input type="text" class="form-control" id="addTitle" placeholder="Title" ng-model="chapters.chapter.title">
</div>
</div>
<div class="col-md-6">
<div class="form-group input-group-sm">
<label>Select Language</label>
<select class="form-control" name="country" id="country" ng-model="chapters.chapter.languageID" ng-options="value.ID as value.language for value in technical.languages">
<option value="">Select Country</option>
</select>
</div>
</div>
</div>
</div>
This part is angularjs code.
$scope.count = 1;
$scope.addChapter = function() {
var iEl = angular.element( document.querySelector('#append-row') );
var wEl = angular.element( document.querySelector('#clone-div') );
iEl.append(wEl.clone());
$scope.count+=1;
};
You should do cloning/repeating inside the template in a ng-repeat and have the data prepared beforehand, that is a much cleaner way. You'll notice for example in the template code you have, all the ng-model's are the same, and will always display the same information if you have 1 'clone' div or 100.
A better method would be to write your clone div in the template and use it as a repeatable ng-template 'script', for example:
// main template
<script type="text/ng-template" id="cloneable.html">
// Your code here, but change reference to ng-model, ie this line as an example:
<input type="text" class="form-control" id="addTitle" placeholder="Title" ng-model="chapters.chapter[$index].title">
</script>
// main template, your new repeat then includes the repeatable script
<div ng-repeat="foo in manyFoos"
ng-include="'cloneable.html'"></div>
This way you can use the $index that arises from ng-repeat, as part of the model to accurately separate each individual repeat block. In your controller, chapters.chapter will be an array of objects.
I don't know about the 'add' button part or what information you're adding, but the above should take care of the model problem you'll be encountering.

angularjs get value from input in recursive template

How'd I get the value to controller from a nested view? I'd like to mention that I have a recursive approach.
HTML
<textarea ng-model="inputValue" class="ng-valid ng-dirty ng-valid-parse ng-touched"></textarea>
Full HTML structure can be found here
Edit:
I want to get the value of the textarea in my controller. (e.g. $scope.inputValue ); currently getting undefined
see this jszfiddle
http://jsfiddle.net/7qbucc62/
<div ng-app="app">
<div ng-controller="firstController">
<textarea ng-model="inputValue"></textarea>
<textarea ng-model="inputValue"></textarea>
</div>
</div>
<script>
(function abc()
{
var app=angular.module("app",[]);
app.controller("firstController",function($scope)
{
$scope.inputValue="";
});
})();
</script>
I think this is what you are asking
you can use $scope.inputValue directly in your controller. It will provide you the value of textarea

AngularJs - model value does not reflect on ui in nested controllers case

I am using angularjs for one of the my module in application. I want to update UI of various locations on page, so that all ui components will work synchronously as the model value changes.
here is my html-
<fieldset ng-controller="controller1" >
<legend>Divs with common controller</legend>
<div style="background-color:#eee;padding:3px;">
<input type="text" ng-model="Model1" />
</div>
<div style="background-color:#eee;padding:3px;">
<input type="text" ng-model="Model1" />
</div>
</fieldset>
<fieldset ng-controller="controller1" >
<legend>Divs with common controller</legend>
<div style="background-color:#eee;padding:3px;" ng-controller="controller2">
<input type="text" ng-model="Model1" />
<input type="text" ng-model="Model2" />
</div>
<div style="background-color:#eee;padding:3px;">
<input type="text" ng-model="Model1" />
</div>
</fieldset>
and my javascript -
var testApp = angular.module('testApp',[]);
var mainApp = angular.module('mainApp',['testApp']);
testApp.controller("controller1",['$scope',function($scope){
$scope.Model1 = "testText";
}]);
testApp.controller("controller2",['$scope',function($scope){
$scope.Model2 = "testText2";
}]);
angular.bootstrap(document, ['mainApp']);
In the html for first fieldset it is working properly. But in second fieldset it is not. So can anyone please tell me how do i achieve the functionality of first fieldset in second fieldset.
Thanks.
use $rootScope instead of $scope
Can you use ng-controller="controller2" to particular input.
Try this
<div style="background-color:#eee;padding:3px;">
<input type="text" ng-model="Model1" />
<input type="text" ng-model="Model2" ng-controller="controller2" />
</div>
It doesn't work because you create 2 seperate scopes/instances for controller1
<div>
// Root scope
<div ng-controller="controller1">
// Child scope A
// scope = new controller1();
</div>
<div ng-controller="controller1">
// Child scope B
// scope = new controller1();
</div>
</div>
You can solve this problem by using the $rootScope directly or by creating a service. The recommended way is to avoid $rootScope whenever possible and use a service instead.
Value is probably the easiest way to create a service. Note that you can also use .service or .factory. Read more in the documentation about services.
testApp.value('myValue', {
data: 'testText'
});
I'm using an object here so we can use this as a reference to the value, this is important for sharing data between controllers. If you want to know why then read more about reference & value types.
Now inject this service into your controller and use this data instead:
testApp.controller("controller1",['$scope', 'myValue',function($scope, myValue){
$scope.Model1 = myValue;
}]);
On the view we need to update the bindings to the reference of the service:
<input type="text" ng-model="Model1.data" />
JSFIDDLE
USE THE DOT! ng-model without "." is bad.
Please read this
What are the nuances of scope prototypal / prototypical inheritance in AngularJS?
The issue is fully described there.

Populate array in angularJS model from view

I am building an angularJS on client side and asp.net as backend. I have a aspx repeater that generate html on server side. I want to populate and array of angular model so that it can be used to make client side interactive application.
<div ng-controller="myController">
<input type="number"id='1' ng-model="number"/>
<input type="number"id='2' ng-model="number"/>
<input type="number"id='3' ng-model="number"/>
<input type="number"id='4' ng-model="number"/>
<input type="number"id='5' ng-model="number"/>
</div>
I want to have all the numbers in an array of my model. is it possible to populate model array from the already generated html.
Make $scope.numbers an array and use ng-repeat like this: $scope.numbers = [1,2,3,4,5];
In your markup:
<div ng-controller="myController" ng-repeat="number in numbers">
<input type="number" id="number{number}" ng-model="number"/>
</div>
When you are generating html code on the server side you can use ngInit to place some data in the scope.
You could write something on the server side:
<div ng-controller="myController" ng-init="myData=[{type:'number', id:1, model:'number1'},{type:'number', id:2, model:'number2'}]">
<div>{{numbers}}</div>
<input ng-repeat="item in myData" type="{{item.type}}" id="{{item.id}}" ng-model="numbers[item.model]"/>
</div>
and your controller could look like this
app.controller('myController', function($scope) {
$scope.numbers = {};
});

Resources