Need to access scope in ng-include directive - angularjs

I need to access the form data (ng-model="name") in the parent controller DynamicFormCtrl . How do i access the data input in the form in the DynamicFormCtrl . I am not getting idea how to i access them.Though the data can be accessed in their own scopes.
<body ng-app="exampleApp" ng-controller="DynamicFormCtrl as ctrl">
<div>
<button ng-click="ctrl.addForm(0)">Form One</button> //add form1
<button ng-click="ctrl.addForm(1)">Form Two</button> //add form 2
<button ng-click="ctrl.addForm(2)">Form Three</button>// add form 3
</div>
<div ng-repeat="form in ctrl.displayedForms track by $index"> //display form on button press
<ng-include src="form"></ng-include> //Include from from the Script
</div>
<script type="text/ng-template" id="form1.tpl.html">
<label>
{{name}}
Form one is an input: <input type="text" ng-model="name"/>
</label>
</script>
<script type="text/ng-template" id="form2.tpl.html">
<label>
Form two gives you choices: <input type="radio"/> <input type="radio"/>
</label>
</script>
<script type="text/ng-template" id="form3.tpl.html">
<button>Form three is a button</button>
</script>
<script type="text/javascript">
angular.module("exampleApp", [])
.controller("DynamicFormCtrl", function($scope) {
var ctrl = this;
$scope.form_name = $scope.name;
console.log($scope.form_name);
var forms = [
"form1.tpl.html",
"form2.tpl.html",
"form3.tpl.html",
];
ctrl.displayedForms = [];
ctrl.addForm = function(formIndex) {
ctrl.displayedForms.push(forms[formIndex]);
}
});
</script>
</body>

As you are using the controller-as syntax you should use ctrl.name in the input field
<input type="text" ng-model="ctrl.name"/>
In the controller you can then use the input by using ctrl.name
You then also do not need to inject the scope as you use the controller-as syntax.
For further reading to controller-as I recommend
https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md

Related

Writing an adding function in AngularJS

I'm new to AngularJS and I am doing some tutorials to get in touch with it. While I'm doing the tutorials I have modified the code a bit to get a better feeling of what's behind. My code consists of two parts, which have nothing to do with each other.
The first one is a simple user input and based on that a list gets filtered. This is working fine.
However, in the second part I was trying to implement a simple adding function where the user can give an input and based on that the sum of two numbers is calculated. This part is not working at all. The numbers are being recognised as strings. The code is basically from this source here. When I copy the whole code and run it, it works fine, but when I modify it a bit it doesn't.
I want to understand why my code isn't working. To me there is nearly no difference. So I think that I eventually misunderstood the concept of angularjs. But I can't figure out where the error could be.
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script type="text/javascript">
function TodoCtrl($scope) {
$scope.total = function () {
return $scope.x + $scope.y;
};
}
</script>
</head>
<body data-ng-app>
<input type="text" ng-model="name">{{name}}
<div data-ng-init="Names=['Arthur', 'Bob', 'Chris', 'David', 'EDGAR']">
<ul>
<li data-ng-repeat="naming in Names | filter: name ">{{naming}}</li>
</ul>
</div>
<div data-ng-controller="TodoCtrl">
<form>
<input type="text" ng-model ="x">{{x}}
<input type="text" ng-model ="y"> {{y}}
<input type="text" value="{{total()}}"/>
<p type= "text" value="{{total()}}">value</p>
</form>
</div>
</body>
</html>
Several things to change...
First you need to create a module:
var app = angular.module("myApp", []);
Then you need to define a module e.g. myApp on the ng-app directive.
<body data-ng-app="myApp">
Then you need to add TodoCtrl to the module:
app.controller("TodoCtrl", TodoCtrl);
Also check that both $scope.x and $scope.y have values, and make sure that they are both parsed as integers, otherwise you will get string concatenation ("1"+"1"="11") instead of addition (1+1=2)!
$scope.total = function () {
return ($scope.x && $scope.y)
? parseInt($scope.x) + parseInt($scope.y)
: 0;
};
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script type="text/javascript">
(function(){
var app = angular.module("myApp", []);
app.controller("TodoCtrl", TodoCtrl);
function TodoCtrl($scope) {
$scope.total = function () {
return ($scope.x && $scope.y)
? parseInt($scope.x) + parseInt($scope.y)
: 0;
};
}
}());
</script>
</head>
<body data-ng-app="myApp">
<input type="text" ng-model="name">{{name}}
<div data-ng-init="Names=['Arthur', 'Bob', 'Chris', 'David', 'EDGAR']">
<ul>
<li data-ng-repeat="naming in Names | filter: name ">{{naming}}</li>
</ul>
</div>
<div data-ng-controller="TodoCtrl">
<form>
<input type="text" ng-model ="x">{{x}}
<input type="text" ng-model ="y"> {{y}}
<input type="text" value="{{total()}}"/>
<p type= "text" value="{{total()}}">value</p>
</form>
</div>
</body>
</html>
As mentioned in the above two answers adding TodoCtrl as controller instead function will make the snippet work.
REASON:
Angularjs framework above 1.3 does not support global function which means declaring controller as function wont work.
In your code snippet, you are using angular version 1.5, which needs the controller to be defined.
DEMO
angular.module("app",[])
.controller("TodoCtrl",function($scope){
$scope.x = 0;
$scope.y = 0;
$scope.total = function () {
return parseInt($scope.x) + parseInt($scope.y)
};
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" >
<input type="text" ng-model="name">{{name}}
<div data-ng-init="Names=['Arthur', 'Bob', 'Chris', 'David', 'EDGAR']">
<ul>
<li data-ng-repeat="naming in Names | filter: name ">{{naming}}</li>
</ul>
</div>
<div data-ng-controller="TodoCtrl">
<form>
<input type="text" ng-model ="x">{{x}}
<input type="text" ng-model ="y"> {{y}}
<input type="text" value="{{total()}}"/>
<p type= "text" value="{{total()}}">value</p>
</form>
</div>
</div>
you need to define the TodoCtrl as controller instead function
.controller("TodoCtrl",function($scope){
$scope.x = 0;
$scope.y = 0;
$scope.total = function () {
return parseInt($scope.x) + parseInt($scope.y)
};
})
Demo
angular.module("app",[])
.controller("TodoCtrl",function($scope){
$scope.x = 0;
$scope.y = 0;
$scope.total = function () {
return parseInt($scope.x) + parseInt($scope.y)
};
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" >
<input type="text" ng-model="name">{{name}}
<div data-ng-init="Names=['Arthur', 'Bob', 'Chris', 'David', 'EDGAR']">
<ul>
<li data-ng-repeat="naming in Names | filter: name ">{{naming}}</li>
</ul>
</div>
<div data-ng-controller="TodoCtrl">
<form>
<input type="text" ng-model ="x">{{x}}
<input type="text" ng-model ="y"> {{y}}
<input type="text" value="{{total()}}"/>
<p type= "text" value="{{total()}}">value</p>
</form>
</div>
</div>

Angular Wiring up two controllers from Model to auto fill form

I've got an angular app I'm working on where I'm trying to auto fill a pop up modal based on a user's selection.
I thought I could use my model service to keep track of what the user selected and 'wire' the controller for the <select> list and it's edit button to the model but that doesn't seem to work.
Adding to the complexity I'm using angular-route and my <select> list is buried in a view. I was trying to keep my pop up modals in a separate controller outside the view because they've got their own templates and I had problems when I nested them into the view...
I've seen a few examples of wiring up angular apps and thought I understood them but I can't figure out what I'm doing wrong.
EDIT (thanks Pankaj Parkar for pointed out my mistakes in the plunker):
I have a plunker here:
https://plnkr.co/edit/6f9FZmV8Ul6LZDm9rcg9?p=preview
Below is the snipped in a single HTML page with CDN links :).
Am I just completely misunderstanding how angularjs is suppose to work?
<html ng-app="myApp">
<head>
<title>Bootstrap 3</title>
</head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<body>
<div ng-view></div>
<script id="editables.html" type="text/ng-template">
<div class="container">
<div class="jumbotron">
<form>
<div class="form-group">
<select class="form-control" id="mapsSelect" size="10" multiple ng-model="model.selected">
<option ng-repeat="n in editables">{{n}}</option>
<select>
</div>
<a href="#editModal" class = "btn btn-info" data-toggle="modal" ng-click="edit()" >Edit</a>
</form>
</div>
</div><!--end container div-->
</script>
<div ng-controller="modalsController">
<div id="editModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<form class="form-horizontal">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4>New Map</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label for="name" class="col-lg-3 control-label">Name</label>
<div class="col-lg-9">
<input type="text" class="form-control" id="name" ng-model="formModel.name"></input>
</div>
</div>
<div class="form-group">
<label for="desc" class="col-lg-3 control-label">Description</label>
<div class="col-lg-9">
<input type="text" class="form-control" id="desc" ng-model="formModel.desc"></input>
</div>
</div>
<div class="modal-footer">
<pre> {{ formModel | json }}<br><br>Working: {{ workingMap }}</pre>
Cancel
Continue
</div>
</form>
</div>
</div>
</div><!-- end modal -->
</div>
</body>
<script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src = "https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular-route.min.js"></script>
<script src = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- <script src = "js/script.js"></script> -->
<script>
var app = angular.module('myApp', ['ngRoute']);
var modelService = function ($log){
var moduleHello = function(myMessage){
console.log("Module hellow from myService " + myMessage);
}
var moduleNames = {
"First" : {desc: "First's Description"},
"Second" : {desc: "Second's Description"},
"Third" : {desc: "Third's Description"}
};
var moduleWorkingName = {};
return {
hello: moduleHello,
editables: moduleNames,
workingName: moduleWorkingName
}
}//end modelService
app.factory("modelService", ["$log", modelService]);
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/editables', {
controller: "editablesController",
templateUrl: "editables.html"
}).
otherwise({
redirectTo: "/editables"
});
}]);
app.controller('editablesController', ['$scope', '$log','modelService', function($scope,$log, $modelService) {
$scope.model = {};
//console.log( JSON.stringify( $modelService.editables ) );
$scope.editables = [];
for ( name in $modelService.editables){
$scope.editables.push( name );
}
$scope.edit = function(){
if ( typeof $modelService.editables [$scope.model.selected] != 'undefined'){
$modelService.workingName = $modelService.editables [$scope.model.selected];
console.log ("Setting my working name to " + JSON.stringify( $modelService.workingName ) );
}else{
console.log ("Nothing Selected");
}
}
}]);
app.controller('modalsController', ['$scope','modelService', function($scope,$modelService) {
$scope.formModel = {};
$scope.formModel.name = "Hard coding works of course";
$scope.formModel.desc = $modelService.workingName.desc; //But I can't seem to get this to update. I thought pointing it at an object in the Model would be enough.
console.log("Firing up modalsController");
}]);
</script>
</html>
I spent the last two days mulling over this in my head and I think I figured it out. For starters, here's the (working) plunker:
https://plnkr.co/edit/Kt3rebPtvGTt0WMXkQW4?p=preview
Now, the explanation. I was trying to keep a separate 'formModel' object that kept track of the controller's state. But that's both silly and pointless.
Instead what you're supposed to do is:
a. Create an object in your service to hold all your data (I just called this 'model')
b. For each controller that needs to share data create a variable on the $scope of the controller and point it to your 'model' variable from your service.
c. after that use the variables from your model in your html.
So in both my controllers you'll find this line:
$scope.model = $modelService.model;
and in my HTML you'll find stuff like this:
<input type="text" class="form-control" id="name" ng-model="model.workingName.name"></input>
notice how I'm using "model.workingName.name"? This references $scope.model.workingName.name, which thanks to the line $scope.model = $modelService.model from my JavaScript now points directly to my model.
And that is how you "wire up" Angular.
By the way, experienced Angular folks have probably noticed that this part:
$scope.editables = [];
for ( name in $modelService.model.names){
$scope.editables.push( name );
}
probably belongs in a directive instead of a controller because I'm editing the DOM.
Stuff like that's what makes it so hard to learn AngularJS. There's so many concepts to get the hang of.

Variable not rendering in {{ }} but only in ng-bind

I'm facing a problem in AngularJS and I'm not able to solve it.
I have a simple search bar in my html code :
<html ng-app="webApp">
<body>
<div class="row" ng-controller="IndexController">
<div class="col-lg-6 col-lg-offset-3 text-center">
<form>
<div class="input-group">
<input type="text" class="form-control" id="search_input" placeholder="Search for..." ng-model="search">
<span class="input-group-btn">
<button class="btn btn-default" type="submit" ng-click="research()"><i class="glyphicon glyphicon-search"></i></button>
</span>
</div>
</form>
Search : {{search}}
<span ng-bind="search"></span>
</div>
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
<script src="./static/javascripts/angular/angular.module.js" type="text/javascript"></script>
<script src="./static/javascripts/angular/controllers/index.controller.js" type="text/javascript"></script>
</html>
My module is declared in an external file :
angular.module('webApp', ['ui.bootstrap', 'elasticsearch', 'angular-highlight']);
I have a simple controller which is binding the value from a search bar :
angular.module('webApp').controller('IndexController', IndexController);
function IndexController($scope, $window, $http) {
$scope.search = '';
$scope.research = function(){
console.log($scope.search);
window.location.href = "http://localhost:4000/results?search=" + $scope.search + "&size=20";
};
}
So my problem is that I my variable search is well rendered in the ng-bind directive but not at all between {{ }}. I have no errors in my console.
Would you have an idea why ?
Thank you in advance for your help.
Regards
Be aware of "scope soup". Since you are passing modules into your application, there is a possibility of an non-aliased controller having the same $scope.search variable. I recommend aliasing your controller on the markup [ex. IndexController as IndexCtrl] and in the controller change $scope to a this reference.
Example:
var vm = this; //preference
this.search = '';
this.research = function(){
console.log(vm.search);
window.location.href = "http://localhost:4000/results?search=" + vm.search + "&size=20";
};
Additionally, you would then reference the search variable in your markup like this:
search: {{IndexCtrl.search}}
Depending on you intent, you may also want to inject the $location service into your controller and replace window.location.href(...) with $location.path(...)
Remember that ngBind is for one-way binding where as ngModel is for two-way binding!

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>

Uncheck checkbox with submit - AngularJS

I am trying to uncheck checkbox with submit button. The idea is when checkbox is checked button is shown, and when button is clicked checkbox is unchecked and button is hidden.
HTML page:
<html ng-app="myApp" ng-controller="myCtrl">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
<script src="script.js"></script>
<meta charset=utf-8 />
</head>
<body>
<div ng-repeat="foo in boxes">
<div>
<input type="checkbox" name="cb" id="cb" ng-model="show" />{{foo}}
</div>
<div ng-show="show">
<form ng-submit="submit()">
<input type="submit" name="sumbit" id="sumbit" value="Hide" />
</form>
</div>
</div>
</body>
</html>
JS:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.boxes = ['a','b','c'];
$scope.submit = function(){
$scope.show = false;
}
});
On Plukner: http://plnkr.co/edit/z9W0w18dkgYJ3D5Q3aR2?p=preview
Thanks for any help!
The problem is that you're using a single variable to store states of 3 items yet Angular creates a scope for each context in the ng-repeat iteration. By changing show to an array and using $index to reference each of them, the show array from the main scope is passed to all three child scopes and there are no conflicts, so it works:
app.controller('myCtrl', function($scope) {
$scope.boxes = ['a','b','c'];
$scope.show = [];
$scope.submit = function(){
$scope.show = [];
}
});
HTML
<div ng-repeat="foo in boxes">
<div>
<input type="checkbox" name="cb" id="cb" ng-model="show[$index]" />{{foo}}
</div>
<div ng-show="show[$index]">
<form ng-submit="submit()">
<input type="submit" name="sumbit" id="sumbit" value="Hide" />
</form>
</div>
</div>
See it here: http://plnkr.co/edit/kfTMaLTXWtpt7N9JVHAQ?p=preview
(note sure if this is exactly what you wanted because there's no question, but it's enough to get you started)
UPDATE
And here is the version where Hide unchecks only "its own" checkbox ($scope.submit now accepts the index parameter): http://plnkr.co/edit/YVICOmQrPeCCUKP2tBBl?p=preview
You need to change the html code and simplify it as
Instead of form use simple ng-click
<div ng-show="show">
<input type="submit" value="Hide" ng-click="show = !show" />
</div>

Resources