ng-class not working. Where did I do wrong? - javascript

I know there are many problems here listed like this. but I can't pinpoint where I did wrong..
<li ng-repeat="item in type.sub | orderBy:y" ng-click="openpic($parent.$index, $index)" ng-class="{ 'active': $parent.$index + ':' + $index == current }">
we have $scope.current variable, and a nested menu with numbering id like 1:2, 1:3, 1:4, 2:1, 2:2, 2:3 and so on.
Goal is very simple. I need to make this <li> active, if the $parent.$index:$index is equal to $scope.current. ID is set whenever openpic($parent.$index, $index) triggered. We have li.active class in css.
So, can someone please show me, what's missing in that code?
TRY 1:
Tried:
<li ng-repeat="item in type.sub | orderBy:y" ng-click="openpic($parent.$index, $index)" ng-class="{ 'active': $parent.$index + ':' + $index == $parent.current }">
Still not working.
TRY 2
I have something like this:
ng-class="{{ $parent.$index + ':' + $index == $parent.current && 'active' || '' }}"
and it shows as ng-class="active" but class attribute did not updated.
TRY 3
ng-class="{{ $parent.$index + ':' + $index == $parent.current && 'highlight' || '' }}"
it shows ng-class='highlight", but class still shows class="ng-binding ng-scope"
TRY 4
ng-class="isActive($parent.$index,$index)"
It solves the problem, but it seems a little bit overkill for a simple switch function. Any more ideas?
TRY 5
As per major-mann code suggestion that works at TRY 4, I made these adjustment, and surprisingly, it works.
ng-class="$parent.$index + ':' + $index == $parent.current && 'active' || ''"
That one works. Removed all braces completely ????

First of all make {{$parent.$index:$index}} to make sure to get the right data (I just never met such a method to data access) ;
If it's ok, then try use:
ng-class="$parent.$index:$index === current ? 'active' : ''"
Or (best way) use function for this:
ng-class="someFn($parent.$index)"
$scope.someFn = function(index){
//index, index:index, index[n] or something else;
return index === $scope.current ? 'active' : '';
};
Update:
If You want get access to parent ng-repeat, better use
<... ng-repeat="(index1, data1) in firstData">
<... ng-repeat="(index2, data2) in secondData">
<... ng-something="index1 operator index2 or function(index1, index2)">
I hope, it will help;

As pointed to in the comments, rather a non-answer, but usually it is best practice to try to keep code (even simple ternaries) inside the JavaScript blocks rather than inside the HTML. This generally makes debugging any issues you may be having infinitely easier to deal with.
So, for example, you could change your HTML to something like:
<li ng-repeat="..." ng-click="..." ng-class="isActive($parent.$index, $index)">
And in your controller, you could add something like:
$scope.menu= function isActive(pidx, idx) {
return {
active: pidx + ':' + idx === $scope.current
};
};
To achieve your desired result.
If you take this a step further, you will probably realize that it is even better to do something like
$scope.cls.menu = function(pidx, idx) {
return {
active: pidx + ':' + idx === $scope.current,
any: 'other',
dynamic: 'classes',
you: 'need'
};
}
And call the function appropriately in the view.

Related

Concatenate/Join Template Elements with a "+"

Is there a way to concatenate template elements? I have this template, which is a loop, but I can't figure out how I can concatenate/join multiple items. If I place the + inside the <kbd> tag, I get an extra + at the end and it is within the kbd tag (which I would like outside of the tag).
<template>
<kbd v-for="(v, i) in item" :key="i">{{ v }}</kbd>
</template>
The data I am using looks something like this (I am actually using a store):
data: () {
return {
item: [ 'a', 'b', 'c' ]
}
}
The result I am looking for is:
<kbd>a</kbd> + <kbd>b</kbd> + <kbd>c</kbd>
Easy enough. Conditional rendering based on index. Something similar to this should work:
<template v-for="(v, i) in item">
{{i > 0 ? ' + ' : ''}}<kbd :key="i">{{ v }}</kbd>
</template>

Why is the 1 in this index + 1 showing up in my directive?

I created a directive with an $index:
HTML:
<tr
reportrowgroup
ng-repeat="report in reports | orderBy: sortBy track by $index"
report="report"
rowindex="{{$index + 1}}"
JS:
'<td>{{rowindex + 1}}</td>'+
scope: {
report: '=',
rowindex: "#"
It works but the result looks like this:
11
21
31
It seems like the 1 is being added in rowindex + 1. How to output the usual 1, 2, 3, etc?
You are passing the correct value to directive using rowindex="{{$index + 1}}". The problem is inside the directive, you should use '{{rowindex}}'. I think this will solve your problem.
It looks like $index is being interpreted as a string. Try this instead:
rowindex="{{ Number($index) + 1 }}"
You can do subtraction instead :)
rowindex="{{ $index - -1 }}"
or
"{{($index-0) + 1}}"

Else if in angular js template [duplicate]

This question already has answers here:
if else statement in AngularJS templates
(10 answers)
Closed 8 years ago.
I need to use else if in angularjs template .What is the syntax ?
For example in c i would write the code like below:
if (data.sender=='system')
{data.receiver}
else if (data.sender=='mail')
{data.receiver}
else {data.sender}
My code:
{{data.sender == 'System' ? data.receiver : ' '}}
{{data.sender =='mail' ? data.receiver : data.sender }}
{{(data.sender === 'system' || data.sender === 'mail') ? data.receiver : data.sender}}
There are no if-else syntax in angular templates as you are looking for. Too much logic in the templates makes it difficult to maintain. Here are two possible solutions:
<span ng-show="data.sender == 'mail' || data.sender=='system'">{{data.receiver}}</span>
<span ng-show="data.sender != 'mail' && data.sender!='system'">{{data.sender}}</span>
You can also use ng-switch in a similar way:
<span ng-switch="data.sender">
<span ng-switch-when="mail">{{data.receiver}}</span>
<span ng-switch-when="system">{{data.receiver}}</span>
<span ng-switch-default>{{data.sender}}</span>
</span>
The later having the advantage that only one of the spans will exist in the document where ng-show/ng-hide all spans exist in the document they are just hidden using display:none.
Other options would be writing your own directive, or creating special filters.
Here it is, but you should really try to avoid having this kind of complicated logic inside of templates, as a rule of thumb.
{{ data.sender == 'system' ? data.receiver : data.sender == 'mail' ? data.receiver : data.sender }}
If you need an elseif in angular template you can use a ternary operator as in C/C++
{{ data.sender=='system'
< 4 ? data.receiver : data.sender=='mail' ? data.receiver : data.sender}}
angular.module('quetion_app', []);
angular.module('quetion_app').controller('quertion_controller', ['$scope',
function($scope) {
$scope.data = {
sender: 'some sender',
receiver: 'somebody'
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="quetion_app">
<div ng-controller="quertion_controller">
{{data}}
<br>
<br>
{{ data.sender=='system'
< 4 ? data.receiver : data.sender=='mail' ? data.receiver : data.sender}} </div>
</div>
Change data.sender in snippet to check the behavior
Hope it helps
This type of logic really belongs in the controller or service which is responsible for setting up data in your $scope. Placing it in your view brings a lot of logic in to the view unnecessarily and also causes that logic to be run as a watch which both expensive and unnecessary.
In the code that establishes data you could have:
data.displayedSender = (data.sender === 'system' || data.sender === 'mail') ? data.receiver : data.sender;
Then in your view you bind to the data.displayed sender:
<span>{{data.displayedSender}}</span>

How JQuery handles with getElementsByClassName iteration?

Today I was shortening my old codes and I saw this code:
$(".ceker").append("<a href='kit/");
$("#pdf").append("pdf");
$("#txt").append("txt");
$("#epub").append("epub");
$(".ceker").append("/7.");
$("#pdf").append("pdf");
$("#txt").append("txt");
$("#epub").append("epub");
$(".ceker").append("'><div class='menukitap'><div class='menuharry7 menuharresler'></div><h4>Ölüm Yadigarları İndir</h4></div></a>");
it used to output like that:
<div class="menukitap"><div class="menuharry7 menuharresler"></div><h4>Ölüm Yadigarları İndir</h4></div>
And I made it shorter like this:
function item()
{
if( $('.ceker').attr('id') == 'pdf' )
{
return "pdf";
}
if( $('.ceker').attr('id') == 'txt' )
{
return "txt";
}
if( $('.ceker').attr('id') == 'epub' )
{
return "epub";
}
}
$(".ceker").append("<a href='kit/" + item() + "/7." + item() + "'><div class='menukitap'><div class='menuharry7 menuharresler'></div><h4>Ölüm Yadigarları İndir</h4></div></a>");
This code works too, but I don't why it does. In my opinion, this code shouldn't work because the class "ceker" has already had 3 different IDs "pdf" 'txt' and "epub"
So here's my question: How JQuery handles with getElementsByClassName Iteration (answer 1)? (I do not understand how this works if( $('.ceker').attr('id') == 'pdf' ))
And here is the HTML if you need to
<nav class="menu">
<span class="ara-menu-yer">Türkçe</span>
<a><li><section id="pdf" class="ceker"></section></li></a>
<a><li><section id="txt" class="ceker"></section></li></a>
<a><li><section id="epub" class="ceker"></section></li></a>
<span class="ara-menu-yer">English</span>
<a><li><section id="ingpdf" class="cekereng"></section></li></a>
<a><li><section id="ingdoc" class="cekereng"></section></li></a>
</nav>
I'm sorry for bad spelling, grammar or vocabulary mistakes if there is. And I think that I couldn't explain my issue but I wish you can understand.
From the docs:
Get the value of an attribute for the first element in the set of matched elements.

AngularJS - HTML data binding UI issue

I am binding following in my HTML.
<div>{{user.address[0].addressline1}}, {{user.address[0].addressline2}}, {{user.address[0].city}}, {{user.address[0].state}}, {{user.address[0].zipcode}}</div>
The issue is if addressline1 is null, it unnecessarily shows the , at first.
And also some other fields can be null
So How to display comma only if the value is not null?
Or as a matter of style, you can use a turnery operator to check for the value then format it
{{ !!user.address[0].addressline1 ? user.address[0].addressline1 + ', ' : ''}}
This could be made as filter to be more intuitive
angular.module('myapp', []).filter('trailIfTrue', [function(){
return function(val, trail){
return !!val ? val + trail : '';
}
}]);
usage:
{{ user.address[0].addressline1 | trailIfTrue:',' }}
here is a plunker
User separate span and ng-show so the span will be shown only if user.address[0].addressline1 is not null
<span ng-show="user.address[0].addressline1">{{user.address[0].addressline1}},</span>
<span ng-show="user.address[0].addressline2">{{user.address[0]. addressline2}},</span>
<span ng-show="user.address[0].city">{{user.address[0].city}},</span>
//...
You can use any expression into ng-show Eg:
user.address[0].addressline1 != null
myObj.myIntAttr > 0 && < 10
myObj.myBoolAttr == false
//...

Categories

Resources