Use angular-translate to set placeholder value onblur - javascript

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;
};
});

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.

Pass value from input to controller without $scope

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", [])

AngularJS currency filter on input field

I have the following input field
<input type="text" class="form-control pull-right" ng-model="ceremony.CeremonyFee | number:2">
it is showing up correctly but has been disabled. The error I am receiving is "[ngModel:nonassign] Expression 'ceremony.CeremonyFee | number:2' is non-assignable". I understand why it is in error, but do not know how to get this to work on an input field. Thanks.
input with ng-model is for inputting data, number filter is for displaying data. As filter values are not bindable, they are not compatible, as you can see. You have to decide what you want to do with that input.
Do you want it to be an input? User can input his own number and you only needs to validate? Use i.e. pattern attribute:
<input type="text" ng-model="ceremony.CeremonyFee" pattern="[0-9]+(.[0-9]{,2})?">
Do you want it to be an output? User does not need to input his own value? Do not use ng-model, use value instead:
<input type="text" value="{{ceremony.CeremonyFee | number:2}}" readonly>
UPDATE:
really I don't understand what you need, but, if you want just that users can insert only two digits you should use a simple html attributes, have a look on min, max, step...
Follows a pure js solution, but I don't suggest something like that!
angular.module('test', []).controller('TestCtrl', function($scope) {
var vm = $scope;
var testValue = 0;
Object.defineProperty(vm, 'testValue', {
get: function() { return testValue; },
set: function(val) {
val = Number(val);
if(angular.isNumber(val) && (val < 100 && val > 0)) {
console.log(val);
testValue = val;
}
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<section ng-app="test">
<div ng-controller="TestCtrl">
<input style="display:block; width: 100%; padding: 1em .5em;" type="number" ng-model="testValue" />
</div>
</section>
the ng-model directive requires a viewmodel assignable (or bindable) property, so, you cannot add a pipe...
angular.module('test', [])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test" ng-init="testValue = 0">
<label ng-bind="testValue | currency"></label>
<input style="display:block;" ng-model="testValue" type="number"/>
</div>
As an error states you have got an 'non-assignable' expression in your ng-model attribute.
You should use only ceremony.CeremonyFee.
| is used on ng-repeat to indicate what expression should be used as filter.
If you want to have that <input> populated with initial data in your controller/link you should give it an initial value ex.
$scope.ceremony = {
CeremonyFee: 'My first ceremony'
}
And every time your <input> element data will be changed CeremonyFee will be updated as well.
I found and used the solution found on this page.
http://jsfiddle.net/k7Lq0rns/1/
'use strict';
angular.module('induction').$inject = ['$scope'];
angular.module('induction').directive('format',['$filter', function ($filter) {
  return {
require: '?ngModel',
link: function (scope, elem, attrs, ctrl) {
if (!ctrl) return;
ctrl.$formatters.unshift(function (a) {
return $filter(attrs.format)(ctrl.$modelValue)
});
elem.bind('blur', function(event) {
var plainNumber = elem.val().replace(/[^\d|\-+|\.+]/g, '');
elem.val($filter(attrs.format)(plainNumber));
});
}
  };
}]);
relatively easy to apply it.

How to reset validation with angular on reset?

In our angular application we have a form with validation and a reset button. We based it off of the examples in the documentation: https://docs.angularjs.org/guide/forms
The trouble happens when someone tries to reset the form when a field is in an invalid state. My expectation is that upon reset, the field should be reset to an initial value and any validation will also be reset. However, I haven't figured out how to clear the validationl.
This can be demonstrated in the aforementioned example from the documentation: https://docs.angularjs.org/guide/forms Load the demo and type in an invalid email address (potatoes) and then press reset. It resets valid fields, but not invalid. We have tried using $setPristine() and fiddling with $valid hasn't led anywhere either. This seems like a straight forward usecase, but I have not been able to find any answers. Please someone point how the trivial solution we have overlooked!
Update: added code from https://docs.angularjs.org/guide/forms
<div ng-controller="ExampleController">
<form novalidate class="simple-form">
Name: <input type="text" ng-model="user.name" /><br />
E-mail: <input type="email" ng-model="user.email" /><br />
Gender: <input type="radio" ng-model="user.gender" value="male" />male
<input type="radio" ng-model="user.gender" value="female" />female<br />
<button ng-click="reset()">RESET</button>
<button ng-click="update(user)">SAVE</button>
</form>
<pre>form = {{user | json}}</pre>
<pre>master = {{master | json}}</pre>
</div>
<script>
angular.module('formExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.master = {};
$scope.update = function(user) {
$scope.master = angular.copy(user);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.reset();
}]);
</script>
I had the same issue, and I found the solution here: https://github.com/angular/angular.js/issues/10027#issuecomment-62857430
The solution is to have all fields of the object set with empty value on the first place, and reset with the same kind of empty object instead of using {}.
Here a plunkr which show the solution:
https://plnkr.co/edit/qKAI4OlmCbu2HNM237Z3?p=preview
angular.module('myApp', [])
.controller('myCtrl', ['$scope', function ($scope) {
function getEmpty() {
return {
name: '',
contact: {email: ''}
};
}
$scope.manufacturer = getEmpty();
$scope.reset = function() {
$scope.manufacturer = getEmpty()
$scope.form.$setPristine();
$scope.form.$setUntouched();
$scope.form.$setValidity();
}
}]);

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