Pass value from input to controller without $scope - javascript

I have problem with following code. I can solve the issue with $scope, but this time request to do it without using $scope in controller. I am using "controller as" to control the view.
<body ng-app="appModule" >
<div ng-controller="calculatorController as calc">
<input type="number" name="firstDigit" placeholder="insert num" ng-model="calc.firstDigit">
<input type="number" name="secondDigit" placeholder="insert num" ng-model="calc.secondDigit">
<span>{{calc.result}}</span>
</div>
</body>
(function(){
angular
.module("calculatorModule")
.controller("calculatorController", calculatorController)
function calculatorController(){
var calc = this;
calc.result = calc.firstDigit + calc.secondDigit;
}
})();

Well, you have two options - you can do it with watchers, or with a function to get the result. I prefer the latter, but it's up to you. Here's an example of how you can get it to work:
Side note - learn the controller as syntax, it will save you thousands of headaches down the road with nested scoping and child-parent relationship issues with $scope -- here's a great article explaining controller as
(function () {
angular.module("calculatorModule", [])
.controller("calculatorController", [function() {
var calc = this;
calc.getResult = function() {
return calc.firstDigit + calc.secondDigit;
}
calc.result = calc.getResult();
}]);
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="calculatorModule" ng-controller="calculatorController as calc">
<input type="number" name="firstDigit" placeholder="insert num" ng-model="calc.firstDigit">
<input type="number" name="secondDigit" placeholder="insert num" ng-model="calc.secondDigit">
<span>{{calc.getResult()}}</span>
</div>

Your module definition is false!
Should be
module("calculatorModule", [])

Related

Angular directive ng-model working for arrays but not string

The ng-model directive seems to be lacking a reference to the actual object within the JavaScript, but only for string values. Using the list of dictionary objects and looping over the elements with ng-repeat as shown below though, it works.
I can only think that it may be due to returning the array acts like returning a reference to the object, whereas returning the string variable is simply returning the literal string, neutralizing the Angular's ability to do it's two-way data binding and leaving me with a variable that still holds a value of undefined.
Why is my service module below unable to pull the updated value from the view for the variable gitRelease?
In a service module I have this functionality:
(function () { //start iife
'use strict';
angular.module('gms.autoDeploy')
.factory('AutoDeployService', ["$http", "$q", "$log", "$cookies", "APP_CONFIGS", "SweetAlert", "$timeout", "GridSettingsService", "APP_USER", AutoDeployService]);
function AutoDeployService($http, $q, $log, $cookies, APP_CONFIGS, $timeout, SweetAlert, GridSettingsService, APP_USER) {
var tibcoCopyJobs = [];
var gitRelease = "";
function addNewTibcoCopyJob() {
tibcoCopyJobs.push({
sourceServer: "",
sourcePath: "",
destinationServer: "",
destinationPath: ""
});
}
function getTibcoCopyJobs() { return tibcoCopyJobs; }
function getGitRelease(){ return gitRelease; }
function extractFormData() {
console.log(gitRelease);
for (var i = 0; i < tibcoCopyJobs.length; i++) {
console.log(tibcoCopyJobs[i]);
}
}
return {
addNewTibcoCopyJob: addNewTibcoCopyJob,
getTibcoCopyJobs: getTibcoCopyJobs,
getGitRelease: getGitRelease,
extractFormData: extractFormData
};
} //end AutoDeployService
}()); //end iife
Using it with this controller:
angular.module("gms.autoDeploy").controller('AutoDeployController', ['$scope', '$compile', 'AutoDeployService',
function ($scope, $compile, AutoDeployService) {
var model = this;
init();
function init() {
model.tibcoCopyJobs = AutoDeployService.getTibcoCopyJobs();
model.gitRelease = AutoDeployService.getGitRelease();
}
function btn_addNewTibcoCopy() { AutoDeployService.addNewTibcoCopyJob(); }
function btn_extractFormData() { AutoDeployService.extractFormData(); }
model.btn_addNewTibcoCopy = btn_addNewTibcoCopy;
model.btn_extractFormData = btn_extractFormData;
}
]);
To give functionality to this view:
<div ng-controller="AutoDeployController as autoDeploy">
<div class="container-fluid">
<div class="row">
<div class="col-md-2">
<input type="text" class="form-control" ng-model="autoDeploy.gitRelease" placeholder="MM-DD-YYYY">
</div>
</div>
<div class="row">
<fieldset class="col-md-2" style="margin-bottom: 10px" ng-repeat="item in autoDeploy.tibcoCopyJobs track by $index">
<legend>Copy</legend>
<input type="text" class="form-control" placeholder="Source Server..." ng-model="item.sourceServer">
<br/>
<input type="text" class="form-control" placeholder="Source Path..." ng-model="item.sourcePath">
<br/>
<input type="text" class="form-control" placeholder="Destination Server..." ng-model="item.destinationServer">
<br/>
<input type="text" class="form-control" placeholder="Destination Path..." ng-model="item.destinationPath">
</fieldset>
</div>
<button ng-click="autoDeploy.btn_extractFormData()">extract</button>
<button ng-click="autoDeploy.btn_addNewTibcoCopy()">TIBCO copy</button>
</div>
</div>
I think you have explained why in your question. Array is returned by reference, whereas string is just copied by value. But I will try to make it a bit more clear.
When you do
model.gitRelease = AutoDeployService.getGitRelease();
the model object will create property getRelease like this:
{getRelease: "", ... (more properties from the ctrl)}
so whatever you update in the view it will just update the getRelease in the controller.
One possible fix is like what Jags mentioned in the comment.
Or you can make a reference to your service in the ctrl
var model = this;
model.autoDeployService = AutoDeployService;
In your view
<input type="text" class="form-control" ng-model="autoDeploy.autoDeployService.gitRelease" placeholder="MM-DD-YYYY">
that should work.

How to pass a value from Jquery to angular Js?

I have working to pass a value from Jquery to angular js. But I have found undefined in angular js.
My code :
HTML :
<button onclick="change('5')"></button>
<input type="hidden" ng-model="data" id="one" />
<button ng-click="test(data)">Test</button>
JQuery:
function change(data)
{
$("#one").val(data).change();
}
Angular Js :
$scope.test= function(data)
{
console.log(data)
}
But I got undefined. How can I do this ?
You can do it for sure*, however you should probably not, as this blend of jQuery and Angular will soon become hard to maintain. This is not really well-design.
Instead, use angular directives and methods, in your case it's straightforward:
<button ng-click="change('5')"></button>
<input type="hidden" ng-model="data" id="one" />
<button ng-click="test(data)">Test</button>
and in Angular controller:
$scope.change = function(x) {
$scope.data = x;
};
* If you really want it: you need to let Angular know that you have changed the model from outside of digest cycle with manual $("#one").val(data).change(); angular.element($("#one")).scope().$apply();.

Use angular-translate to set placeholder value onblur

I am new to Angular.
Implementing localization in the project. I've got many inputs and I must translate placeholders. In HTML I have something like this
<input type="email" placeholder="{{ 'TRANSLATION_KEY' | translate }}" onfocus="this.placeholder=''" onblur="this.placeholder='{{ 'TRANSLATION_KEY' | translate }}'" required>
But this part of the code doesn't work:(
onblur="this.placeholder='{{ 'TRANSLATION_KEY' | translate }}'"
How to set translated value to placeholder onblur?
I'll appreciate any help!
I have another solution. More universal and easy. Just add this line to your input in the view
onfocus="this.ph=this.placeholder;this.placeholder=''" onblur="this.placeholder=this.ph"
This is a good approach to the problem JSFiddle:
HTML:
<div ng-app="myApp" ng-controller="myCtrl">
<input type="email" placeholder="{{placeholder}}" ng-focus="setPlaceholder()" ng-blur="setPlaceholder('TRANSLATION_KEY')" required>
</div>
JS:
angular.module('myApp', [])
.controller('myCtrl', function ($scope, $filter) {
$scope.placeholder = $filter('translate')('TRANSLATION_KEY');
$scope.setPlaceholder = function (data) {
$scope.placeholder = $filter('translate')(data);
};
})
.filter('translate', function () {
return function (data) {
return data;
};
});

How the controller in angular is called?

I want to bind the full name = firstname + lastname.
I have seen this example in the w3 schools. But i am unable to understand it.
My question is how the function got called? It have any listeners?
Could someone please, shed some light on it, in detailed way. Sorry I am newbie..
My code is:
var application = angular.module('myTempApp', []);
application.controller('myController', function ($scope) {
$scope.myFirstName = "xxx";
$scope.myLastName = "yyy";
$scope.myFunction = function () {
alert('called');
$scope.myFullName = $scope.myFirstName + $scope.myLastName;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body>
<div ng-app="myTempApp" ng-controller="myController">
<input type="text" ng-model="myFirstName" />
<input type="text" ng-model="myLastName" />
<input type="text" ng-model="myFullName" ng-bind="myFullName" />
<br />
{{ myFunction() }}
<br/>
data ::: {{2+2}}
</div>
</body>
Thanks in advance.
lets go step by step.
You are binding three literals and one function type variable. Whenever you write any variable (of any data type), it gets registered in the digest cycle of angularJS. So, firstName, lastName, fullName and myFunction gets registered in digest cycle. And every variable in digest cycle has a watcher.
Whenever a variable changes, angularJS checks through all variables registered in digest cycle and prints the latest value of each variable in the view.
so lets assume - if firstName is xxx and last name is yyy and you changed firstName to xx. Now angular will check both firstName and lastName and print the latest value of both of them.
Therefore, whenever you make any change to any scope variable, your binded function inside the angular expression gets called
If you want to update a variable depending on other could use $watch
var application = angular.module('myTempApp', []);
application.controller('myController', function ($scope) {
$scope.myFirstName = "xxx";
$scope.myLastName = "yyy";
$scope.myFunction = function () {
//alert('called');
$scope.myFullName = $scope.myFirstName + $scope.myLastName;
};
$scope.$watch("myFirstName + myLastName", $scope.myFunction);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body>
<div ng-app="myTempApp" ng-controller="myController">
<input type="text" ng-model="myFirstName" />
<input type="text" ng-model="myLastName" />
<input type="text" ng-model="myFullName" ng-bind="myFullName" />
<br />
{{ myFunction() }}
<br/>
data ::: {{2+2}}
</div>
</body>
This might help.
function studentController($scope) {
$scope.student = {
firstName: "Mahesh",
lastName: "Parashar",
fullName: function() {
var studentObject;
studentObject = $scope.student;
return studentObject.firstName + " " + studentObject.lastName;
}
};
}
Enter first name: <input type="text" ng-model="student.firstName"><br>
Enter last name: <input type="text" ng-model="student.lastName"><br>
<br>
You are entering: {{student.fullName()}}
There two ways of binding data between the model (html and the controller the data into the $scope, ng-bind and {{ }}. What they do here is call {{ myFunction() }} ((which act like a listener), then every time is taking care of myFirstName and myLastName (so as they change, the new value is going to be save in $scope.myfullName, and render into the model)

Dynamically assign ng-model

I'm trying to generate a set of check-boxes from an object array. I'm aiming to have the check-boxes dynamically map their ng-model to a property of the new object that will be submitted into the array.
What I had in mind is something like
<li ng-repeat="item in items">
<label>{{item.name}}</label>
<input type="checkbox" ng-model="newObject.{{item.name}}">
</li>
This doesn't work as can be seen on this JSFiddle:
http://jsfiddle.net/GreenGeorge/NKjXB/2/
Can anybody help?
This should give you desired results:
<input type="checkbox" ng-model="newObject[item.name]">
Here is a working plunk: http://plnkr.co/edit/ALHQtkjiUDzZVtTfLIOR?p=preview
EDIT
As correctly noted in the comments using this with ng-change requires a "dummy" ng-model to be present beforehand. It should however be noted that apparently with 1.3 the required options have been provided by the framework. Please check out https://stackoverflow.com/a/28365515/3497830 below!
/EDIT
Just in case you are like me stumbling over a simple case while having a more complex task, this is the solution I came up with for dynamically binding arbitrary expressions to ng-model: http://plnkr.co/edit/ccdJTm0zBnqjntEQfAfx?p=preview
Method: I created a directive dynamicModel that takes a standard angular expression, evaluates it and links the result to the scope via ng-model and $compile.
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.data = {};
$scope.testvalue = 'data.foo';
$scope.eval = $scope.$eval;
});
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.data = {};
$scope.testvalue = 'data.foo';
$scope.eval = $scope.$eval;
});
app.directive('dynamicModel', ['$compile', function ($compile) {
return {
'link': function(scope, element, attrs) {
scope.$watch(attrs.dynamicModel, function(dynamicModel) {
if (attrs.ngModel == dynamicModel || !dynamicModel) return;
element.attr('ng-model', dynamicModel);
if (dynamicModel == '') {
element.removeAttr('ng-model');
}
// Unbind all previous event handlers, this is
// necessary to remove previously linked models.
element.unbind();
$compile(element)(scope);
});
}
};
}]);
Usage is simply dynamic-model="angularExpression" where angularExpression results in a string that is used as the expression for ng-model.
I hope this saves someone the headache of having to come up with this solution.
Regards,
Justus
With Angular 1.3, you can use ng-model-options directive to dynamically assign the model, or bind to an expression.
Here is a plunkr: http://plnkr.co/edit/65EBiySUc1iWCWG6Ov98?p=preview
<input type="text" ng-model="name"><br>
<input type="text" ng-model="user.name"
ng-model-options="{ getterSetter: true }">
More info on ngModelOptions here: https://docs.angularjs.org/api/ng/directive/ngModelOptions
This is my approach to support deeper expression, e.g. 'model.level1.level2.value'
<input class="form-control" ng-model="Utility.safePath(model, item.modelPath).value">
where item.modelPath = 'level1.level2' and
Utility(model, 'level1.level2') is the utility function that returns model.level1.level2
<!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">
<form name="priceForm" ng-submit="submitPriceForm()">
<div ng-repeat="x in [].constructor(9) track by $index">
<label>
Person {{$index+1}} <span class="warning-text">*</span>
</label>
<input type="number" class="form-control" name="person{{$index+1}}" ng-model="price['person'+($index+1)]" />
</div>
<button>Save</button>
</form>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function ($scope) {
$scope.price = [];
$scope.submitPriceForm = function () {
//objects be like $scope.price=[{person1:value},{person2:value}....]
console.log($scope.price);
}
});
</script>
</body>
</html>

Categories

Resources