Scope inheritance with ng-bind (not working) vs {{ }} (working) - angularjs

I am learning AngularJS and just done with the scope inheritance. Following is the sample code I wrote. I am referencing angular version 1.5.0
HTML
<div ng-controller="ScopeInheritanceParentController" class="scope_inheritance_parent">
<span>Parent</span><br /><br />
<!--<span ng-bind="title" /><br /><br />-->
<span>{{title}}</span><br /><br />
<input type="text" ng-model="title" /><br /><br />
<div ng-controller="ScopeInheritanceChildController" class="scope_inheritance_child">
<span>Child</span><br /><br />
<!--<span ng-bind="title" /><br /><br />-->
<span>{{title}}</span><br /><br />
<input type="text" ng-model="title" />
</div>
</div>
JS
angular.module('myapp.controllers')
.controller('ScopeInheritanceParentController', ['$scope', function ($scope) {
$scope.title = "Initial title set by Parent controller ctor function"
}])
.controller('ScopeInheritanceChildController', ['$scope', function ($scope) {
$scope.title = 'Initial title set by Child controller ctor function'
}])
So far so good and I get the output as:
Issue
When I comment {{title}} syntax and uncomment ng-bind="title" span I see the output as:
Where is Child controller now?
Why is it not displaying text box from Parent controller?
I know that {{}} syntax creates a watcher internally and thus angular is able to update view when expression changes. I also read that ng-bind is same as {{}}, so I would assume it works the same way.

span tag has such syntax
<span ng-bind='title'></span>

Related

Upload image within ng-submit form

I'm new to Angular.js and I would like to know how to upload an image within my ng-submit form. It works perfectly for the next based fields but with the file it only gives me the 'choose file' button without displaying it after hitting the submit button.
<form ng-submit="addartikel()">
<input type="text" placeholder="Bezeichnung" ng-model="newartikel.name" />
<input type="text" placeholder="Kategorie" ng-model="newartikel.kategorie" />
<input type="text" placeholder="Preis" ng-model="newartikel.preis" />
<input type="file" placeholder="Bild" ng-model="newartikel.thumb" />
<input type="submit" value="Artikel hinzufügen" />
As for the controller:
webShop.controller('InventarController', ['$scope', '$http', function($scope, $http){
$scope.addartikel = function(){
$scope.inventar.push({
name: $scope.newartikel.name,
kategorie: $scope.newartikel.kategorie,
preis: parseInt($scope.newartikel.preis),
thumb: $scope.newartikel.thumb,
available: true
});
Your help would be greatly appreciated :)
Use Angular File Upload.It is available in https://github.com/nervgh/angular-file-upload

Udating parent object from isolated scope in directive is not working at all

I have a directive defined like that:
myApp.directive('someDirective', function() {
return {
restrict: 'A',
scope: {
disableButton: '=',
},
templateUrl: 'sometemplate.html',
controller: 'SomeDirectiveController'
}
});
The controller for the directive looks as follows:
mLoan.controller('GiversDirectiveController', function (
$scope,
) {
$scope.checkGiversAmount = function () {
var giversCurrentTotalValue = $scope.stocksTotalAmount - $scope.giversCurrentAmount;
}
this is the directive view
<div class="row">
<div class="col-lg-2">
<label for="customer">Wybierz klienta</label>
<select id="customer"
name="customer"
class="form-control"
ng-model="selectedCustomerId"
ng-options="customer.Id as customer.Name for customer in customers"
ng-change="getGiversFunds(selectedCustomerId)"
required=""></select>
</div>
<div class="col-lg-2" ng-show="customerFunds.length > 0">
<label for="customerFunds">Wybierz fundusz</label>
<select id="customerFunds"
name="customerFunds"
class="form-control"
ng-model="selectedFundId"
ng-options="customerFund.Id as customerFund.Name for customerFund in customerFunds"
ng-blur="updateGiverFund(selectedCustomerId, selectedFundId)"
ng-required="customerFunds.length > 0"></select>
</div>
<div class="col-lg-2">
<label for="giversCurrentAmount">Ilość</label>
<input type="number" min="1"
max="{{giversCurrentAmount}}"
id="giversCurrentAmount"
name="giversCurrentAmount"
class="form-control"
ng-model="giversCurrentAmount"
ng-change="checkGiversAmount(selectedFundId)"
ng-blur="updateGiverStockAmount(selectedCustomerId, giversCurrentAmount)"
required />
</div>
<div class="col-lg-2">
<label for="commission">FEE%</label>
<input type="number"
min="1"
id="commission"
name="commission"
class="form-control"
ng-model="commission"
ng-blur="updateGiverCommission(selectedCustomerId, commission)"
required />
</div>
<div class="col-lg-4">
<label for="minimalCommission">FEE Min</label>
<input type="number"
min="1"
id="minimalCommission"
name="minimalCommission"
class="form-control"
ng-model="minimalCommission"
ng-blur="updateGiverMinimalCommission(selectedCustomerId, minimalCommission)"
required />
</div>
</div>
And a parent view where I'm Using the directive with the button:
<div ng-repeat="giver in givers">
<div givers-directive givers="givers"
givers-current-amount="giversCurrentAmount"
disable-giver-side-add="parent"
stocks-total-amount="stocksTotalAmount">
</div>
</div>
<div class="row">
<div class="col-lg-12 margin-top-10px">
<button id="addGiverSide"
name="saveLoan"
class="btn btn-primary"
ng-click="addGiverSide(AddLoansForm)"
ng-disabled="disableButton">
Dodaj
</button>
</div>
</div>
Now my problem and question ath the same time is how I can update the disableButton from the parent model. Before you say this is a duplicate I've ran through the solutions taht was on stackoverflow mainly this one: How to access parent scope from within a custom directive *with own scope* in AngularJS? and that one: What are the nuances of scope prototypal / prototypical inheritance in AngularJS? but nothing seems to help. What is straneg (or not) I can't use the $parent to get to that. I have to go through: $scope.$parent.$parent path and then it's getting updated. Besides that it looks ugly and strange, it's not working when I'm trying to updated this variable from the parent view. To sum up one effect is working and the other is not. And after changing is the other way around. I've tried to wrap up the disable button into an object and try to do the change but this does not work also. Or maybe I'm doing it wrong. Please kindly help me because I'm running out of ideas. What am I doing wrong?
UPDATE
I'm adding the rest of the directive view to show the concept what I'm trying to achieve here. THere are drop downs wich I want them to be independent. Because without the directive with separated (or isolated) scope the two dropdowns are getting filled by changing the other. I want to change them indepenently. I've managed to achieve thet through out the isolated scope. But now I can't seem to get the disabling button working.
By defining a scope inside your directive, you lock your directive out of the parent's scope. If you want to make use of a parent scope, you should set your scope to true.
You can read more on the matter here: http://www.sitepoint.com/practical-guide-angularjs-directives/
EDIT: Example
myApp.directive('someDirective', function() {
return {
restrict: 'A',
scope: true,
templateUrl: 'sometemplate.html',
controller: 'SomeDirectiveController'
}

Get value from HTML input element from Angularjs controller

I'm trying to get the value from an HTML element from Angular controller.
<div ng-app="myApp" ng-controller="myControler">
<br />
<input id="Text1" type="text" runat="server" value="aValue" /
My controller :
var myApp = angular.module('myApp', []);
myApp.controller("myControler", function ($scope, $document) {
var name = angular.element($('#Text1')).val();
console.log(name);
});
But name returns "undefined"...
Please, what I'm doing wrong ?
angular.element is an alias for jquery $.
You could access that element like this: angular.element('#Text1').val();
ng-model is the angular way to do this though. You can set the value from ASP using ng-init
<input id="Text1" type="text" runat="server" ng-model="inputVal" ng-init="inputVal='aVal'">
And this can be accessed from the controller using the scope console.log($scope.inputVal);
JSfiddle example: http://jsfiddle.net/n1oppeu2/
Why you need angular element to access form element ??
You can get and set value by binding model to it
like this
<input id="Text1" type="text" runat="server" ng-model="input.field1" />
controller
$scope.input={
field1:''
}
Using angular element selector #
<input id="Text1" type="text" runat="server" value="aValue" />
console.log(angular.element('#Text1').val());
or
console.log(angular.element('#Text1')[0].value);

Angular form validation using the controllerAs syntax

I am currently facing the following problem:
I would like to validate my form input using the Angular ngModel directives.
When using those together with $scope they work fine.
Now, working with the controllerAs syntax, they fail to work.
This problem is poorly documented, the only help I could find is this article.
Here is a small example of my code:
The template gets called with myController as vm
<form name="vm.signUpForm" ng-submit="vm.signup(vm.user)">
<label for="name">Name</label>
<input type="text"
class="form-control"
id="name"
name="name"
placeholder="Full name"
ng-model="vm.user.name"
ng-minlength="2" required />
<div ng-show="vm.signUpForm.$submitted || vm.signUpForm.name.$touched">
<span ng-show="vm.signUpForm.name.$error.required">Please fill in your name</span>
<span ng-show="vm.signUpForm.name.$error.minlength">A minimum of 2 [...]</span>
</div>
[...]
</form>
Am I forced to use $scope to validate the form? Or did I miss something ?
Thanks in advance!
Solution by: Andrew Gray
I had to change the following lines to get this to work:
<form name="vm.signUpForm" ... >
<!-- To -->
<form name="signUpForm" ...>
<div ng-show="vm.signUpForm.$submitted || vm.signUpForm.name.$touched">
<!-- To -->
<div ng-if="signUpForm.name.$invalid">
<span ng-show="vm.signUpForm.name.$error.required" ... >
<!-- To -->
<span ng-show="signUpForm.name.$error.required" ... >
First things first - you don't need the vm. on the form.
<form novalidate name="someForm">
<label>
Some Text:
<span class="danger-text" ng-if="someForm.someText.$invalid">
ERROR!
</span>
</label>
<input type="text" name="someField" />
</form>
The way it winds up working, is that there's a validation object that is not tied to the scope. The controllerAs syntax is just spinning off a instance of the controller as a scope variable.
Try shaving off the vm. from the form and child elements' names, and you should be OK.

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.

Resources