I am displaying my nested for loop correctly but I am having trouble when highlighting the individual selected li element in the nested array, so the undesired result is everything in that row highlights based on whatever number i is.
<div class="nopadding week" style="width: 12%;" *ngFor="let day of Schedule; let j = index">
<ul class="nopadding">
<div *ngFor="let hour of day.hours; let i = index" class="hours">
<li class="hour" [ngClass]="{watched: hour.assignments.length> 0, unassigned: hour.assignments.length <= 0}" (click)="selectedtimeslot(hour.assignments, i)" [class.active]="i == selectedRow">
{{hour.assignments.length}}
</li>
</div>
</div>
</ul>
</div>
In my component I have the function that set that value of the selected row.
selectedtimeslot(item: any, index:any) {
this.selectedRow = index;
this.highlightGuardian.changeNav(item);
}
scss
li.active {
background-color:#123456 !important;
color: white;
}
I think I know my problem is that I am nit giving the [class.active] any information about the parents index in order to correctly highlight the selected element
You are correct that your issue is you aren't giving it any parent information, so it is highlighting the selected index of every parent.
Instead of making your selectedRow be equal to a number, make it an hour, and send it the hour, like so.
<div *ngFor="let hour of day.hours; let i = index" class="hours">
<li class="hour" [ngClass]="{watched: hour.assignments.length> 0, unassigned: hour.assignments.length <= 0}" (click)="selectedtimeslot(hour.assignments, hour)" [class.active]="hour == selectedRow">
{{hour.assignments.length}}
</li>
</div>
This will ensure that it only matches that single div, as it will do an object compare, instead of an index compare.
Related
I am trying to build a To-Do list in Vue.js which has 3 columns: To-Do, Doing, Done.
I would like to be able to move an item between columns by clicking on arrows that are inside the list item.
Right now I have a list of objects that I separate in 3 arrays depending on a "status" attribute. I would like to change that attribute when clicking on left/right arrow then refresh the UI with new arrays.
I haven't found the way to target the element that received the click.
<ul>
<li v-for="todo in todoTodos" v-bind:key="todo._id">
<span v-if="todo.importance == 1" class="bg-success"></span>
<span v-else-if="todo.importance == 2" class="bg-warning"></span>
<span v-else-if="todo.importance == 3" class="bg-alert"></span>
<div>
<h3>{{ todo.title }}</h3>
<p>{{ todo.description }}</p>
</div>
<p class="todo__date">Début: {{ todo.datebegin }} - Fin espérée: {{ todo.dateend }}</p>
<div class="todo__actions">
<i #click="editTodo" class="icofont-edit"></i>
<i #click="moveRight" class="icofont-arrow-right"></i>
<i #click="moveLeft" class="icofont-arrow-left"></i>
</div>
</li>
</ul>
My linter prevents me from using v-for + v-if, but I guess that means I will have to re-calculate each list (todoTodos, doingTodos, doneTodos) after each modification. Is there a better way ?
I tried console.logging this e.target e.currentTarget but
this logs the entire data model
e.target and e.currentTarget logs the element which I can't use to find my way back to the todo item I want to modify
You /usually/ pass the ($event) argument to a method if you want to access an event.
<i #click="moveLeft($event)" class="icofont-arrow-left"></i>
......
methods: {
moveLeft(e){
console.log(e.target)
}
}
I am using angular js with multiple conditions all using the same id. Need to get text just from the condition that is true.
I just found a big bug in an app I'm about to release.
I am using angularjs/ionic vs 1 and use allot of conditions in my html.
These condition produce great results and show what I want to be shown.
However whenever I save the information it fetches the element id, which each condition has the same id, and instead of giving me the text to the visible condition, I get all of them.
I need a way to grab the id text only if it's visible. This used to work, unless this was missed during testing.
Checking the id in controller.
function JqliteIds(id) {
// var myElement = angular.element( document.querySelector( '#some-id' ) );
var p = angular.element(document.getElementById(id)).text().trim();
p = p.replace(/(\r\n|\n|\r)/gm, " ");
p = p.replace(/ +/g, ' ');
return p;
//stepTwoFormula = stepTwoFormula.replace(/(\r\n|\n|\r)/gm, " ");
//stepTwoFormula = stepTwoFormula.replace(/ +/g, ' ');
}
The html form with multiple conditions. The id is... id="stepOneFormula"
<div class="item item-text-wrap">
<div ng-if="level.light">
<div ng-show="level.stepOne.bleachAdditiveType < 0">
<p id="stepOneFormula">
Mix {{config.productTypes[level.stepOne.productType]}} with
<span ng-if="level.stepOne.productType === 1 || level.stepOne.productType === 2">
the manufacturer suggested developer or
</span> {{level.stepOne.peroxideVolume}} volume / {{level.stepOne.peroxidePercentage}} percent peroxide until it is the consistency of mayonnaise.
</p>
</div>
<div ng-show="level.stepOne.bleachAdditiveType > -1">
<p id="stepOneFormula">
Add approximately {{config.partsInches[level.stepOne.bleachInches]}} of
{{config.productTypes[level.stepOne.bleachAdditiveType]}} to {{config.productTypes[level.stepOne.productType]}}. Mix with
<span ng-if="level.stepOne.productType === 1 || level.stepOne.productType === 2">
the manufacturer suggested developer or
</span> {{level.stepOne.peroxideVolume}} volume / {{level.stepOne.peroxidePercentage}} percent peroxide until it is the consistency of mayonnaise.
</p>
</div>
</div>
<div ng-if="!level.light">
<p>
<!--Going Red-->
<div ng-show="level.stepOne.redRootsTonePercentOne > -1">
<div id="stepOneFormula" ng-include="'app/formula-result/service-types/double-process/red-rootsDbl1.html'"></div>
</div>
<!--Mixed Levels of gray-->
<div ng-show="level.stepOne.grayTonePercentFour > -1">
<div id="stepOneFormula" ng-include="'app/formula-result/service-types/double-process/gray-mixedDbl1.html'" data="level.stepOne"></div>
</div>
<!--Regular Levels-->
<div ng-show="level.stepOne.grayTonePercentFour === -1 && level.stepOne.redRootsTonePercentOne === -1">
<div id="stepOneFormula" ng-include="'app/formula-result/service-types/double-process/genericDbl1.html'"></div>
</div>
</p>
</div>
</div>
As soon as I posted this question I started reading on the ng-show, ng-if and changed my ng-shows to ng-if... it worked.
https://docs.angularjs.org/api/ng/directive/ngIf
Don't need to check if element is visible. Unlike ng-show, the ngIf directive removes or recreates the element. So if it isn't created it's not there so the id is irrelevant.
So this is the snippet of my code, the aim here is to either hide or show the h4 element based on my condition.
<h4 ng-hide="data_startupcosts.note == ' '">THE COST OF STARTING THIS VENTURE</h4>
<div ng-repeat="data_startupcosts in data.startupcosts track by $index">
{{data_startupcosts.note}}
<ul ng-repeat="data_startupcosts_lists in data_startupcosts.list track by $index">
<li>
I used ng-hide with an expression but no luck...... any suggestions?????
You use the data_startupcosts outside your ng-repeat, so that variable won't exist in there. Instead use it inside your ng-repeat scope:
<div ng-repeat="data_startupcosts in data.startupcosts track by $index">
<h4 ng-hide="data_startupcosts.note == ' '">THE COST OF STARTING THIS VENTURE</h4>
{{ data_startupcosts.note }}
<ul ng-repeat="data_startupcosts_lists in data_startupcosts.list track by $index">
<li>..</li>
</ul>
</div>
Or, if you really want it outside the div, use ng-repeat-start:
<h4 ng-repeat-start="data_startupcosts in data.startupcosts track by $index"
ng-hide="data_startupcosts.note == ' '">THE COST OF STARTING THIS VENTURE</h4>
<div ng-repeat-end>
{{ data_startupcosts.note }}
<ul ng-repeat="data_startupcosts_lists in data_startupcosts.list track by $index">
<li>..</li>
</ul>
</div>
Also make sure your condition is correct, you are comparing with a single space, but maybe there isn't any space? (data_startupcosts.note == '')
<div class="right">
<a class="waves-effect waves-light btn"
ng-repeat="answer in question.answers"
ng-click="answer.isSelected = !answer.isSelected">
{{ answer.letter }}
</a>
</div>
That's my code. I have many answers and I want the user to select one. I have that part working. The part I don't have working is I want to set the isSelected for all other answers to false. How can I accomplish this?
Keep in mind, my data is SUPER nested. So question is part of a ng-repeat="question in instructionSet.questions" and instructionSet is part of another ng-repeat and so on.
If there is only one element you can select, it's better to have one parameter so save the state instead of having it on every object.
<div class="right">
<a class="waves-effect waves-light btn"
ng-repeat="answer in question.answers"
ng-click="$parent.question.selectedAnswer =
$parent.question.selectedAnswer == answer ? null: answer">
{{ answer.letter }}
</a>
</div>
Pretty simple - declare a variable above the repeat scope, lets say selectedIndex and set it to -1
$scope.selectedIndex = -1;
Now set this to the selected index on click if it's not already, or back to -1 if it's already selected:
ng-click="setIndex($index)">
And the method:
$scope.setIndex = function(idx) {
$scope.selectedIndex = $scope.selectedIndex === idx ? -1 : idx;
}
I am looking for a way to sort a fairly complicated html unordered list using either standard javascript or jQuery.
Please view the HTML, the order needs to be alphabetical and based on the HTML found inside the ".keywordType span value" but needs to construct the order of the top level li (with the unique keyword_xxx). I've just pasted 2 of the list items out of dozens.
<ul class="keywords">
<li id="keyword_185">
<div class="icon_keyword"></div>
<input type="hidden" class="keywordLabel" value="More opening hours">
<div class="data-wrapper">
<div class="keywordType">
<span class="oh">Payment methods</span>
</div>
<div class="keywordValue">
<span id="keyword_185" class="oh">Credit Card, PayPal</span>
</div>
</div>
<a class="edit" title="Edit keywords"></a>
<a class="delete" title="Delete keywords"></a>
</li>
<li id="keyword_192">
<div class="icon_keyword"></div>
<input type="hidden" class="keywordLabel" value="Monday to Friday: 8:30am to 6:30pm Saturday: 9pm to 6:30pm Sunday: 10 - 4pm">
<div class="data-wrapper">
<div class="keywordType">
<span class="oh">Opening Hours</span>
</div>
<div class="keywordValue">
<span id="keyword_192" class="oh">Monday to Friday: 8:30am to 6:30pm<br>Saturday: 9pm to 6:30pm<br>Sunday: 10 - 4pm</span>
</div>
</div>
<a class="edit" title="Edit keywords"></a>
<a class="delete" title="Delete keywords"></a>
</li>
</ul>
Thanks
var list = $('ul.keywords');
var listItems = $('li', list);
listItems.sort(function (a, b) {
return $(a).text() > $(b).text() ? 1 : -1;
});
list.append(listItems);
You can sort the list of elements (jQuery objects have all the methods of Array, including Array.prototype.sort).
In the comparison function simply compare the text content of the list items. Individual letters will be subsequently compared according to their position in the alphabet (Unicode table, actually). For example, k > a is true.
Finally, just re-append the items to the list.
Demo: http://jsbin.com/igesic
Take a look at this, it exactly matches your requirement.
http://james.padolsey.com/javascript/sorting-elements-with-jquery/
Does this help?
var arr;
$('.keyword span').each( function( i, el){
arr[i] = $(el).text();
});
arr.sort();
I tested it on this question page, the code below orders the list of related questions in the right hand col.
var arr;
$('.question-hyperlink').each( function( i, el){
arr[i] = $(el).text();
});
arr.sort();