ngClass style with variable in key - javascript

I hope someone can help me out.
I am using angular v1.3.14 and I try to add a scope variable in a key of a ng-class map.
example
<b class="fixedClass" ng-class="{'classOne' : x === 'foo',
'classTwo-%(y)%' : x === 'bar'}">
%(z)%
</b>
is there any way to do something like this or is there a way around ?

You can do something like this
angular.module('App',[])
.controller('AppController',['$scope',function($scope){
$scope.y = 10;
$scope.val = 'bar';
var fixedClass = "fixedClass ";
$scope.getCSSClass = function(){
if($scope.val === 'foo'){
return fixedClass + 'classOne';
} else {
return fixedClass + 'classTwo-(' +$scope.y+ ')';
}
};
}])
In Html
<body ng-controller="AppController">
<b ng-class="getCSSClass()">hello</b>
</body>
Here is the working code

Looking at your requirement, it appears you are mixing static class names with dynamic class names. Preferred approach would be
ng-class="['fixedClass',' fixedClass2',getDynamicStyle()]"
getDynamicStyle is exposed in scope to return the value of dynamic class name. You may add any number of dynamic styles.

Related

AngularJS + style is not applied to field

I am trying to apply a color to a message on an api response.
example:
angularJS:
.then(function (response) {
angular.element(document.getElementById("msg")).css('color', '#00662f');
$scope.Messages = response.data;
and my HTML:
<div id="msg" ng-repeat="msg in Messages">{{msg}}</div>
but this line:
angular.element(document.getElementById("msg")).css('color', '#00662f');
does not seem to be applied to the color of the message.
Can you tell what I am doing wrong?
Thank you for your help.
Erasmo
UPDATE - My Solution
added a boolean
$scope.IsColor == true;
Set it to false/true based on the API response:
if (response.data.indexOf("sucessfully added") !== -1) {
$scope.Messages = response.data;
$scope.IsColor = true;
angular.element("#msg").focus()
return true;
}
else {
$scope.Messages = response.data;
$scope.IsColor = false;
angular.element("#msg").focus()
return false;
}
Then in the HTML
<div id="msg" ng-repeat="msg in Messages" ng-class="$scope.IsColor ? 'text-green' : 'text-red'">{{msg}}</div>
You should do it via ng-class or ng-style. Please see stackblitz for how to update style:
https://stackblitz.com/edit/angularjs-puf49l
Beside the style, in your HTML:
<div id="msg" ng-repeat="msg in Messages">{{msg}}</div>
You should replace id with class, using id's to identify elements is often considered a bit bad, because id's are global and it would instantly mess up if I happen to have a collision.
Try this
angular.element(document.querySelector("msg")).css('color', '#00662f');

How can I correctly use variable variable names in ng-repeat in angular?

HTML:
<ul>
<li ng-repeat="comic in comiclist">
<span>{{ comic.title }} : {{comic.id}}</span>
<div >
<img ng-src="{{comic.thumbnail.path}}.{{comic.thumbnail.extension}}"/>
</div>
<div>
<ul>
<li ng-repeat="character in charlist + {{comic.id}}">
<span>{{character.name}}</span>
</li>
</ul>
</div>
</li>
</ul>
JS with angular
var App = angular.module('MarvelApp', []);
App.controller('MainController', function($scope,$window, $http) {
$scope.GetSeries = function(){
$http.get('http://gateway.marvel.com/v1/public/series?')
.then(function(response){
$scope.serieslist = response.data.data.results;
});
};
$scope.GetComics = function(){
$http.get('http://gateway.marvel.com/v1/public/series/' + $scope.selectedseries + '/comics?')
.then(function(response){
$scope.comiclist = response.data.data.results;
});
//comic in comiclist contains comic.id
//which needs to go to GetCharacter()
}
$scope.GetCharacter = function(comicid){
$http.get('http://gateway.marvel.com/v1/public/comics/' + comicid + '/characters')
.then(function(response){
$scope.['charlist' + comicid] = response.data.data.results;
//this list needs to be displayed in the second ng-repeat
});
};
});
I'd like to get the character list to display in the right div. How I had it set up before, (without $scope.['charlist' + comicid]) it was overriding the other ng-repeats too.
Also, whenever GetComics() gets called it does it automatically.
I don't think $scope.[] is valid syntax (unless I've been missing out on a nifty trick).
You should instead name an "associative array" under $scope something like:
$scope.charlist[comicid] = ... ;
Your ng-repeat would then look something like:
<li ng-repeat="character in charlist[comic.id]">
EDIT As mentioned in the comments, $scope.charlist must be defined before the above lines can be used. This can happen in a few ways:
Make a check before you set it: if(!$scope.charlist) $scope.charlist = [];
Define it somewhere in the controller with $scope.charlist = [];
Of course there's any number of ways you can do this, but these make these I believe make the most sense, the first of which catches invalid states i.e. if for some reason $scope.charlist is set to null it would create a new "associative array".

how to display name of a particular code from a javascript object in angular js and html5

I have a angular controller that has the following array which has 3 values.
controller.medicalInstitues;
I want to take the 4th object in the array with code "AUS". Then further, I want to display the name of only 2 medical institutes with the code as "SYD" and "MEL" within that choosen bject from the parent array.
something like below:
var country = select controller.medicalInstitues.countryCode = "AUS"
var institues = select controller.medicalInstitues.name from country.code="SYD" and "MEL";
now I need to bind these in the UI (Angular).
<span class="code"> {{ controller.institutes.name }}</span>
Suppose you have got your list of values in medicalInstitues, then in the angularjs controller you can do
$scope.institues = medicalInstitues.filter(function(value){
return value.countryCode == "AUS" && (value.code == "SYD" || value.code == "MEL");
});
In HTML you can use ng-repeat:
<div controller="controller">
....
<span ng-repeat="institue in institues">{{institue.name}}</span>
....
</div>
In your controller, to bind the 4th object in your array you can set:
$scope.AUS = yourArray[3]
Then in the html you can show the object properties:
{{ AUS."object path to name" }}
Well, if I understood your question well, you can do the following:
// If you have an array that you already know that will come 4 items with the same country code, you can simply do:
$scope.medicalInstitues = array[3];
// Otherwise:
$scope.medicalInstitues = array.filter(function (value) {
return value.countryCode == "AUS";
})[3];
// To get all 'institues' with the countryCode equals to 'SYD' or 'MEL':
$scope.institues = array.filter(function (value) {
return value.countryCode == "SYD" || value.countryCode == "MEL";
});

edit update existing array in javascript

I am making CRUD app for learning purpose. I need to update existing javascript array on click of edit button. However currently its not updating the existing array rather then its creating new record. Below is the JS code of controller
For Add screen below is the controller code
.controller('addController', ['$scope','$location','$rootScope', function(scope,location,rootScope){
scope.save = function (){
scope.personName = document.getElementById('name').value;
scope.personDesc = document.getElementById('desc').value;
scope.person = {'name' : scope.personName, 'desc' : scope.personDesc};
if(typeof rootScope.crew === 'undefined'){
rootScope.crew = [];
}
rootScope.crew.push(scope.person);
location.path("/");
}
}])
For Edit Screen, below is the code of controller :-
.controller('editController',['$scope','$location','$routeParams','$rootScope', function(scope,location,routeParams,rootScope){
var oldName = scope.crew[routeParams.id].name;
document.getElementById('name').value = scope.crew[routeParams.id].name;
document.getElementById('desc').value = scope.crew[routeParams.id].desc;
scope.editSave = function(){
scope.person = {
'name' : document.getElementById('name').value,
'desc' : document.getElementById('desc').value
}
rootScope.crew.push(scope.person);
location.path("/");
}
}])
Currently I am adding record in existing array rather updating.
Please suggest
The problem is you are pushing a new item to the array. You need to just update the existing person with the person in scope.
.controller('editController',['$scope','$location','$routeParams','$rootScope', function(scope,location,routeParams,rootScope){
var person = scope.crew[routeParams.id]
scope.person = {
name = person.name,
desc = person.desc
};
scope.editSave = function(){
scope.crew[routeParams.id] = scope.person;
location.path("/");
}
}])
In your edit view you would have this:
<input type="text" id="name" ng-model="person.name"/>
<input type="text" id="desc" ng-model="person.desc"/>
It's also worth mentioning that there is no need to have code such as document.getElementById as angular will handle the model binding for you so you don't have to interact with the dom using javascript.
Every object that you are pushing in array must be identified by some id.So assign one id attribute to the person object that you are pushing.
Now come to the edit.html
<tr ng-repeat="p in person">
{{p.name}}
//In button I am passing id which I used in editing the person object
<button ng-click="edit(p.id)"></button>
</tr>
//In controller
edit(id){
//firstly search for the person which is going to be updated
for(i=0;i<arrayInWhichYouArePushingData.length;i++)
{
if(arrayInWhichYouArePushingData[i].id==id)
{
arrayInWhichYouArePushingData[i]=UpdatedData;
break;
}
}
This is just an algorithm to solve this type of problem.You have to modify little bit.

angularjs newline filter with no other html

I'm trying to convert newline characters (\n) to html br's.
As per this discussion in the Google Group, here's what I've got:
myApp.filter('newlines', function () {
return function(text) {
return text.replace(/\n/g, '<br/>');
}
});
The discussion there also advises to use the following in the view:
{{ dataFromModel | newline | html }}
This seems to be using the old html filter, whereas now we're supposed to use the ng-bind-html attribute.
Regardless, this poses a problem: I don't want any HTML from the original string (dataFromModel) to be rendered as HTML; only the br's.
For example, given the following string:
While 7 > 5
I still don't want html & stuff in here...
I'd want it to output:
While 7 > 5<br>I still don't want html & stuff in here...
Is there any way to accomplish this?
Maybe you can achieve this only with html, a <preformated text> way ? It will avoid from using filters or do any kind of processing.
All you have to do is display the text within an element that has this CSS:
<p style="white-space: pre;">{{ MyMultiLineText}}</p>
This will parse and display \n as new lines. Works great for me.
Here, a jsFiddle example.
Instead of messing with new directives, I decided to just use 2 filters:
App.filter('newlines', function () {
return function(text) {
return text.replace(/\n/g, '<br/>');
}
})
.filter('noHTML', function () {
return function(text) {
return text
.replace(/&/g, '&')
.replace(/>/g, '>')
.replace(/</g, '<');
}
});
Then, in my view, I pipe one into the other:
<span ng-bind-html-unsafe="dataFromModel | noHTML | newlines"></span>
A simpler way to do this is to make a filter that splits the text at each \n into a list, and then to use `ng-repeat.
The filter:
App.filter('newlines', function() {
return function(text) {
return text.split(/\n/g);
};
});
and in the html:
<span ng-repeat="line in (text | newlines) track by $index">
<p> {{line}}</p>
<br>
</span>
If you do not want to destroy the layout with endless strings, use pre-line:
<p style="white-space: pre-line;">{{ MyMultiLineText}}</p>
I'm not aware if Angular has a service to strip html, but it seems you need to remove html before passing your newlines custom filter. The way I would do it is through a custom no-html directive, which would be passed a scope property and the name of a filter to apply after removing the html
<div no-html="data" post-filter="newlines"></div>
Here's the implementation
app.directive('noHtml', function($filter){
return function(scope, element, attrs){
var html = scope[attrs.noHtml];
var text = angular.element("<div>").html(html).text();
// post filter
var filter = attrs.postFilter;
var result = $filter(filter)(text);
// apending html
element.html(result);
};
});
The important bit is the text variable. Here I create an intermediate DOM element and append it the HTML using the html method and then retrieve only the text with the text method. Both methods are provided by Angular's lite version of jQuery.
The following part is applying the newline filter, which is done using the $filter service.
Check the plunker here: http://plnkr.co/edit/SEtHH5eUgFEtC92Czq7T?p=preview
An update to the filter with ng-bind-html currently would be:
myApp.filter('newlines', function () {
return function(text) {
return text.replace(/(
)?
/g, '<br/>');
}
});
and the noHTML filter is no longer required.
white-space solution is having low browser support:
http://caniuse.com/#search=tab-size
Bit late to the party on this but I would suggest a small improvement to check for undefined / null strings.
Something like:
.filter('newlines', function () {
return function(text) {
return (text) ? text.replace(/(
)?
/g, '<br/>') : text;
};
})
Or (bit tighter)
.filter('newlines', function () {
return function(text) {
return (text instanceof String || typeof text === "string") ? text.replace(/(
)?
/g, '<br/>') : text;
};
})

Categories