concatenate string with scope variable inside ng-model - angularjs

How to concatenate string with scope variable and assign it to ng-model
is there a way ti express this
ng-model="'is'+location.placeName+'Checked'"

You can use ng-bind-model instead of ng-model in this case
ng-bind-model="is{{location.placeName}}Checked"
thanks

Finally found the answer randomly in this plunker by ozkary using ng-init
HTML View
<input ng-model="isPlaceChecked" ng-init="isPlaceChecked = checkIfPlaceChecked(location.placeName)"
JS Controller
$scope.checkIfPlaceChecked = function (placeName) {
return "is" + placeName + "Checked";
}

Related

Convert an express-like string to an expression in Angular view

Assuming that I have an expression-like string in my scope
$scope.expressionString = 'model.key == "anything"'
I want to use this string as an expression in view, can I do that?
In view, I will have something like
<div ng-if="expressionString"></div> but of course, expressionString should be something else instead.
I appreciate any help. Cheers!
You can use $eval to evaluate your expression , there are two ways to do it in your case
Solution 1
<div ng-if="$eval(expressionString)"></div>
Solution 2
In the controller store the evaluated value of the expression like below
$scope.expressionString = $scope.$eval('model.key == "anything"')
and then in the view simply use it without using $eval in the view
<div ng-if="expressionString"></div>
I found the answer, made a parse filter to parse the string and assign it a scope
angular.module('zehitomo')
.filter('parse', function ($parse) {
return function (expression, scope) {
return $parse(expression)(scope);
};
});
And in view
ng-if="expressionString | parse:this"
You cannot use global variables (or functions) in Angular expressions. Angular expressions are just attributes, so are strings and not Javascript code.
Please see this stackoverflow answer once
Although, you can achieve it using a function instead of a variable:
$scope.expressionString = function(toCompare) {
return $scope.model.key == toCompare;
}
and in your view:
<div ng-if="expressionString('anything')"></div>

Compiling a String in Angular Before Displaying

I have the following html:
<div ng-repeat="string in myStrings">
<p>{{string}}</p>
</div>
And a string like this that gets added to $scope.myStrings:
$scope.stringIwantToBeCompiled = 'I want to count to 4 via angular: {{2+2}}';
I would like the string to show 4 instead of the {{2+2}} angular expression.
Am I barking up the wrong tree here by trying to do this via $compile? If not, how is it done? Just putting it in compile fails. Do I absolutely HAVE to do this in a directive?
PLNKR FOR REFERENCE
Not sure what your exact goal is, but I can think of two approaches to accomplish this without compiling:
1) Split up the values like so:
<div ng-repeat="string in myStrings">
<p>{{string}}{{mathValue}}</p>
</div>
in controller:
$scope.mathValue = 2+2;
2) Use a function to return the string (I like using this anytime I'm doing anything binding that is non-trivial):
<div ng-repeat="string in myStrings">
<p>{{stringFunction()}}</p>
</div>
in controller:
$scope.mathValue = 2+2;
$scope.stringFunction = function() {
return 'I want to count to 4 via angular: '+$scope.mathValue;
};
I'm not 100% sure whether you are just wanting to count the number of strings in the myStrings array, or just have the ability to add a count, but given your Plunker, you could do the following:
To simply add two variables, update the following line:
$scope.stringIwantToBeCompiled = 'I want to count to 4 via angular: ' + (2+2);
If you wanted to show the count of the number of strings, swap the order of your scope variable declarations and show the myStrings length
$scope.myStrings = ['I am a string', 'I am another string', 'more strings!'];
$scope.stringIwantToBeCompiled = 'I want to count to 4 via angular: ' + $scope.myStrings.length;
Counting the strings will only give you 3, of course, because there are only 3 strings in the array.
Does that solve it for you?
UPDATE
OK - So I think what you want is the count in the string with an ng-click to correspond to the count correct?
If so, then the following on your ng-repeat would do it...
<p>{{string}} {{$index}} </p>
Using $index gives you the index of the repeating item. You can always add 1 to the $index to make it 1-based instead of zero based:
<p>{{string}} {{$index + 1}} </p>
You can append the angular expresion {{}} to the string like:
$scope.stringIwantToBeCompiled = 'I want to count to 4 via angular: ' + {{stuff or 2 + 2}};
Or use $compile Fiddle example
I really needed to use a directive with $compile like shown here:
app.directive('dynamicAlert', function ($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, ele, attrs) {
scope.$watch(attrs.dynamicAlert, function(html) {
ele.html(html);
$compile(ele.contents())(scope);
});
}
};
});
http://plnkr.co/edit/bJPEyfkKsertulTN7rWp?p=preview

updating ng-model from ng-value directive

I have a situation where I have couple of readonly fields in the form like with others to show the problem
You can see the las two inputs are readonly and they are calculated inputs where total debit is calculated by totalDebit function on $scope and total credit is calculated by totalCredit() function on the $scope. The problem is inputs only reflect ng-model values which is zero for both inputs and does not take value from calculating functions. A simplified controller is
app.controller('myController', ['$scope' ,function($scope){
$scope.credit = 0;
$scope.debit = 0;
$scope.debitSum = 0;
$scope.creditSum = 0;
$scope.totalCredit = function(){
return $scope.credit + 200; //just to show that it is calculated field
}
$scope.totalDebit = function(){
return $scope.debit + 200; //just to show that it is calculated field
}
}]);
If you remove ng-model directive from readonly inputs they will assume their values from totalDebit and totalCredit functions respectively. But I want them to use values from functions and also update $scope properties of totalDebit and totalCredit. Here is the plunker for this code
Should not be answer here (Why the ng-value is not doing what expected):
ngValue
Binds the given expression to the value of <option> or input[radio], so that when the element is selected, the ngModel of that element is set to the bound value.
And that is not our case...
Because, the ngValue is triggered on CHANGE. When we select radio or some option in the <select>
So, ng-value is not the proper setting in this scenario.
We can adjust it like this:
<input name="totalDebit" value="{{totalDebit()}}" readonly="" />
<input name="totalCredit" value="{{totalCredit()}}" readonly="" />
See updated plunker

rootScope is upating on scope variable update

I have created a rootScope variable like
$rootScope.globalData = data;
$rootScope.globalData.chillerConditions.HeatSource.Value = "ST"; //Default Value
$scope.chillerConditions.HeatSource.Value = 1; //Default Value
where data is my returning value from api. Also create a scope variable which is a object contains a list of items.
$scope.chillerAttributes = data.ObjCandidateListChillerAttributes;
$scope.chillerConditions = data.ObjCandidateListConditions;
On HTML I have:
<select ng-model="chillerConditions.HeatSource.Value" style="width:53%;" ng-options="item.Id as item.Description for item in ValidRatingHeatSource" ng-change="heatSourceChanged()" id="ddRatingHeatSource" class="form-control search-select designComboboxHeight" data-container="body"></select>
Here ValidRatingHeatSource is
$scope.ValidRatingHeatSource = \*list of items*\
On change of Drop Down I have written an function. In that
if($scope.chillerConditions.HeatSource.Value == 2)
{
$rootScope.globalData.chillerConditions.HeatSource.Value = "HW";
}
else
{
$rootScope.globalData.chillerConditions.HeatSource.Value = "ST";
}
Till now was the my current code.
Issue is :
When the above function is called then whenever current $rootScope varible i.e. $rootScope.globalData.chillerConditions.HeatSource.Value is changed to "HW" or "ST" it also changing $scope.chillerConditions.HeatSource.Value to "HW" or "ST".
Why so?
Is there any inbuilt functionality in angularjs?
Please suggest if I am making any mistake? New suggestion are also welcome.
This behavior is the way JavaScript works and has nothing to do with AngularJS. JavaScript is an object-oriented (prototype-based) language where objects are addressed by reference and not by value. E.g. assign car2 to car1 and both of them will reference the same object (JSFiddle)
var car1 = {make: "Audi"}
var car2 = car1;
car2.make = "Toyota";
So in your case, $rootScope.globalData.chillerConditions.HeatSource and $scope.chillerConditions.HeatSource are the same object.
Rather, it seems like you want to create a copy. You can do so with angular.Copy
$scope.chillerAttributes = angular.copy(data.ObjCandidateListChillerAttributes);
$scope.chillerConditions = angular.copy(data.ObjCandidateListConditions);
In your example u have both ng-model and ng-change, so:
1. User change value in select.
2. $scope.chillerConditions.HeatSource.Value changes (ng-model)
3. heatSourceChanged starts (ng-change) -> $rootScope.globalData.chillerConditions.HeatSource.Value changes
So everything works as should...

How can I remove all string spaces in AngularJS binding?

I try to do this:
<div id="{{mystring.replace(/[\s]/g, \'\')}}"></div>
but its not working. "mystring" is an object on $scope with string like "my string is this" with spaces I want to remove from the view.
Just create a dedicated filter :
angular.module('filters.stringUtils', [])
.filter('removeSpaces', [function() {
return function(string) {
if (!angular.isString(string)) {
return string;
}
return string.replace(/[\s]/g, '');
};
}])
and call it like :
<div id="{{'hi there'| removeSpaces}}"></div>
If you simply need it in one or two places it may be easier to split and join:
$scope.boundString = 'this is a string with spaces'
with that you could do in your template:
<span>my string is: {{ boundString.split(' ').join('') }}</span>
and you would get:
my string is: thisisastringwithoutspaces
another approach that has been mentioned is the regex version ('g' is for global):
<span>my string is: {{ boundString.replace(/ /g, '') }}</span>
I guess the point is that you can do whatever you want to a string within an expression. These examples are bad convention with respect to Angular dirty-checking. In Angular, bound functions (string.replace, string.split) get evaluated differently opposed to a specified value (string, boolean) when bound to a template's expression. The result of a bound function must be evaluated before Angular knows whether or not to update the DOM. This can be costly over a large app. I would suggest using another variable to track the un-spaced value:
$scope.noSpaces = $scope.boundString.replace(/ /g, '');
HTML:
<span>{{ noSpaces }}</span>
This way, when a digest loop is triggered, Angular will check if noSpaces has changed as opposed to evaluating boundString.replace(/ /g, '').
What if you are ng-repeating? Good question.
for (var idx = 0, idx < $scope.boundIterable.length, i++) {
$scope.boundIterable[i].noSpaces = $scope.boundIterable[i].boundString.replace(/ /g, '');
}
HTML:
<ul ng-repeat="iterable in boundIterable">
<li>{{ iterable.noSpaces }}</li>
</ul>
The directive mentioned works pretty well. But if you want to remove spaces for smaller texts, you can use
.split(" ").join("")
This replaces the complete spaces unlike .replace(" ","") which replaces only the first space.
You can replace all spaces by blank by using replace():
.replace(" ","")
How about {{ string.trim() }}?
Source
You can do it by using replace():
{{mystring.replace(" ","")}}
that's it I hope so.
removeSpaces() {
originalText ="hi! here i'm";
removedSpacesText = originalText.split(" ").join("");
}

Resources