Exclude item on orderBy - javascript

Say I have 4 item in ng-repeat. How can I exclude one item in orderBy?
<li ng-repeat="item in items | orderBy:'id':true">
$scope.items = [
{"name":"item1","id":1},
{"name":"item2","id":2},
{"name":"item3","id":3},
{"name":"item4","id":4}
];
How can I make, say, id:3 always appear as the first item?
plunker demo

You can create a function to alter the value you sort by (plunker):
$scope.itemSortValue = function(item) {
if (item.id == 3)
return -1;
return item.id;
}
Html:
<li ng-repeat="item in items | orderBy:itemSortValue">
{{item.name}}
</li>

Related

while deleting the particular items from iteration of items in click event first item is deleting instead of clciked one

In my angular application I have some iteration items and saving the items based on adding the items.
.component.html
<ng-container *ngFor="let categoryDetail of selectedCategoryDetails">
<div class="__header">
<div>
<b>{{ categoryDetail.category }}</b>
</div>
</div>
<div
class="clinical-note__category__details"
*ngIf="categoryDetail.showDetails">
<ul>
<li class="habit-list"
*ngFor="let habits of categoryDetail.habitDetails" >
<div class="target-details">
<b>{{ clinicalNoteLabels.target }}: </b
><span class="habit-list__value">{{ habits.target }}</span>
</div>
</li>
</ul>
<div class="habit-footer">
<span class="m-l-10"
[popoverOnHover]="false"
type="button"
[popover]="customHabitPopovers"><i class="fa fa-trash-o" ></i> Delete</span>
</div>
<div class="clinical-note__popoverdelete">
<popover-content #customHabitPopovers [closeOnClickOutside]="true">
<h5>Do you want to delete this habit?</h5>
<button
class="btn-primary clinical-note__save" (click)="deletedata(index);customHabitPopovers.hide()">yes </button>
</popover-content></div>
</div>
</ng-container>
.component.ts
public saveHealthyHabits() {
let isCategoryExist = false;
let categoryDetails = {
category: this.clinicalNoteForm.controls.category.value,
habitDetails: this.healthyHabits.value,
showDetails: true,
};
if (this.customHabitList.length) {
categoryDetails.habitDetails = categoryDetails.habitDetails.concat(
this.customHabitList
);
this.customHabitList = [];
}
if (this.selectedCategoryDetails) {
this.selectedCategoryDetails.forEach((selectedCategory) => {
if (selectedCategory.category === categoryDetails.category) {
isCategoryExist = true;
selectedCategory.habitDetails = selectedCategory.habitDetails.concat(
categoryDetails.habitDetails
);
}
});
}
if (!this.selectedCategoryDetails || !isCategoryExist) {
this.selectedCategoryDetails.push(categoryDetails);
}
this.clinicalNoteForm.patchValue({
category: null,
});
this.healthyHabits.clear();
}
public deletedata(index:number){
if (this.selectedCategoryDetails) {
this.selectedCategoryDetails.forEach((selectedCategory) => {
this.selectedCategoryDetails.splice(index, 1);
}}
From the above code I have saved the data based on adding the items as above and my requirement is when we click on the delete(it will show the popup having the button yes implemented in anbove code).
when we click on the yes button from list of items, I have to remove the particular item
When I tried removing ,It is only deleting the first item instead of clicked one
Can anyone help me on the same
The logic for deletion is incorrect. The splice mutates the original array, and you are applying the loop for deletion, which keeps on iterating over the array and deleting the array elements based on index, instead of deleting single matched index element.
Example -
const categories = [
1,
2,
3,
4
];
function removal(i) {
categories.forEach((category, index) => {
categories.splice(i, 1);
});
console.log('----Categories-->', categories);
}
removal(0);
Categories Array
First Iteration [index = 0]
[1,2,3,4]
Loop Starts Iterating from 1
Second Iteration [index = 1]
[2,3,4]
Loop Starts Iterating from 3
Third Iteration [index = 2]
[3,4]
Stop
Instead you can use filter function.
public deletedata(index:number){
this.selectedCategoryDetails = this.selectedCategoryDetails.filter((_, i) => i! == index);
}
Note - I would recommend to delete the categories based on some identifier like id instead of index because the array elements position can get changed.
Instead of passing index to deleteData method, you can pass the category object.
public deletedata(category){
this.selectedCategoryDetails = this.selectedCategoryDetails.filter((c) => c.id! == category.id);
}

How to get 1st true value for *ngIf inside *ngFor

I have an array of items that need to be displayed based on roles. I need the first value which will fulfil the ngIf condition.
I am adding my code below:
My Array(kind of how it will originally look):
parentTabList = [
{
name: 'abc',
label: 'abc',
icon : 'question_answer',
role : ['vend_perm','vend_temp','vend_subs']
},
{
name: 'xyz',
label: 'xyz',
icon : 'question_answer',
role : ['vend_perm','vend_subs']
}
]
My Html: -
<ng-container *ngFor="let form of parentTabList let i = index">
<li *ngIf="form.role.includes(userRole)">
<a (click)="methodName(form)">
{{form.label}}
</a>
</li>
</ng-container>
UserRole is a string value that I get when a user logs-in.
I need to add a ngClass to the anchor tag if it is the first anchor to be displayed.
(I am a noob at StackOverflow, please let me know if any more explanation is required).
You can identify first element of the array with index.
But as per my understanding you need filter this array with roles and then apply ngClass to first element from filtered list.
So add method to return filtered array with respect to roles
In Template:
filterParentTabList(parentList: any) {
return parentList.filter(form => form.role.includes(this.userRole));
}
In View:
<ng-container *ngFor="let form of filterParentTabList(parentTabList); let i = index">
<li>
<a [ngClass]="{ 'addYourClaaName': i === 0 }" (click)="methodName(form)">
{{form.label}}
</a>
</li>
</ng-container>
Happy Coding.. :)
You can write like this. In this code, f represents the first position of your array.
<ng-container *ngFor="let form of parentTabList; let i = index; let f = first">
<li *ngIf="f">
<a (click)="methodName(f)">
`{{f.label}}`
</a>
</li>
</ng-container>
If you want other position of your array, you can write like you mentioned above.
You can define a getter that will get you the index. This can then be used in the html
get firstIndex() {
return this.parentTabList.indexOf(this.parentTabList.find(({role}) =>
role.includes(this.userRole)))
}
Now in your html
<ng-container *ngFor="let form of parentTabList let i = index">
<li *ngIf="form.role.includes(userRole)">
<a [ngClass]="{redText: firstIndex === i}" (click)="methodName(form)">
{{form.label}}
</a>
</li>
</ng-container>
See Stackblitz Demo Here

How to select all with ng-checked and ng-model

I have an Ionic application(it work the same like Angularjs) and I have a little problem.
<ion-list class="list-inset subcategory" ng-repeat="item in shops">
<ion-checkbox class="item item-divider item-checkbox-right" ng-model="selectAll">
{{item}}
</ion-checkbox>
<ion-item ng-repeat="value in data | filter:{shopName: item}" class="item-thumbnail-left" ng-click="openProduct(value)">
...
<div class="row">
<ion-checkbox stop-event='click' ng-model="value.selected" ng-checked="selectAll">{{value.name}}</ion-checkbox>
</div>
...
</ion-list>
When I click on item with ng-model="selectAll" all items is selected. But I have property value.selected. It sets false for each one value. When I click on item with ng-model="value.selected" it changes. But when I want selec all and click on item with ng-model="selectAll" this propety doesn't change.
Help me please.
Note: I have ng-repeat in the ng-repeat. First ng-repeat is for shops, the second is for products. And I have a filter by shopName. And I want select all by shops. Now it works how I want, but doesn't change property value.selected. Value it is produt, item it is shop.
the state of selectAll can be derived from the state of your other check boxes so it should not be stored as a seperate field.
You could use a getterSetter on the selectAll model to determine weather it should be checked. e.g.
<input type="checkbox" ng-model="selectAll" ng-model-options="{getterSetter: true}"/>
JS
var getAllSelected = function () {
var selectedItems = $scope.Items.filter(function (item) {
return item.Selected;
});
return selectedItems.length === $scope.Items.length;
}
var setAllSelected = function (value) {
angular.forEach($scope.Items, function (item) {
item.Selected = value;
});
}
$scope.selectAll = function (value) {
if (value !== undefined) {
return setAllSelected(value);
} else {
return getAllSelected();
}
}
http://jsfiddle.net/2jm6x4co/
you can use ngClick on the item with ng-model="selectAll". you can call a function in ng-click and then make selected=true for all other items where ng-model="value.selected".

Hide or Display an Item with Angular or Jquery?

i am using mvc. I have model and i take data from model to view with this code:
<ul>
<li id="geri"><<</li>
#foreach (var item in Model.Skills)
{
<li id="#String.Format("{0}{1}", "skill", item.SkillId)">
#item.SkillName
</li>
}
<li id="ileri" style="margin-right: 0;">>></li>
</ul>
After first 4 items, they should be hidden (display:none). I searched angular and find ng-show attribute but cannot find how to use. Now my website looks like:
It should be one line and when i pressed next button, first item will hide and 5th item will show.
I hope i can explain myself, thanks
In Angular, try to use limitTo and offset filters.
Here's the Jsfiddle link.
AngularJS sample codes:
HTML:
<div ng-app="myApp">
<ul ng-controller="YourCtrl">
<li ng-click="previousSkills()"><<</li>
<li ng-repeat="skill in skills | offset: currentPage * 4 | limitTo: 4">
{{skill.SkillName}}
</li>
<li ng-click="nextSkills()">>></li>
</ul>
</div>
AngularJS Controller:
'use strict';
var app = angular.module('myApp', []);
app.controller('YourCtrl', ['$scope', function ($scope) {
$scope.currentPage = 0;
$scope.skills = [
{SkillName:'C#'},
{SkillName:'MVC'},
{SkillName:'Web Forms'},
{SkillName:'Web API'},
{SkillName:'SignalR'},
{SkillName:'EF'},
{SkillName:'Linq'},
{SkillName:'Github'},
{SkillName:'Html'},
{SkillName:'CSS'},
{SkillName:'SQL'},
{SkillName:'Angular'},
{SkillName:'Azure'}
];
$scope.previousSkills = function() {
$scope.currentPage = $scope.currentPage - 1;
};
$scope.nextSkills = function() {
$scope.currentPage = $scope.currentPage + 1;
};
}]);
app.filter('offset', function() {
return function(input, start) {
start = parseInt(start, 10);
return input.slice(start);
};
});
Hope it helps.
In Angular your HTML should be something like this to display only the first 4 items <li>, where items is your $scope.items:
<ul>
<li id="geri"><<</li>
<li ng-repeat="(key, item) in items" ng-show="key <= 3">{{item.SkillName}}</li>
<li id="ileri" style="margin-right: 0;">>></li>
</ul>
JSFiddle here

AngularJS list items alphanumerically

I've been working on sorting a list of items alphanumerically. I have found that using ng-repeat with orderBy tends to sort either numerically or alphabetically depending on the type of data it is working with. It does not however sort alphanumerically.
JavaScript Code:
function AppCtrl($scope) {
$scope.items = [
{'name':'School Item 1','address':'1920'},
{'name':'Work Item 2','address':'4192'},
{'name':'Ad Item 5','address':'2039'},
{'name':'Cool Item 45','address':'2090'},
{'name':'Cool Item 50','address':'1029'},
{'name':'Cool Item 100','address':'1829'},
{'name':'Cool Item 400','address':'1728'}
];
}
HTML Code:
<ul ng-controller="AppCtrl">
<li ng-repeat="item in items|orderBy:['name','address']">
{{item.name}} {{item.address}}
</li>
</ul>
Here is the fiddle http://jsfiddle.net/roverton/PuYLS/1/
Notice that when ordered the it will show 1 then 100, 45 then 400, 5 then 50 etc. I would like to order these alphanumerically. How would I do that in AngularJS?
One way to do this is to use a function to extract the number.
function nameNumberSorter(item) {
var numberPart = item.name.replace('NamedItem', '');
return parseInt(numberPart);
}
And then alter your filter a bit:
<div ng-app>
<ul ng-controller="AppCtrl">
<li ng-repeat="item in items|filter:deviceBindingFilter|orderBy:nameNumberSorter">
{{item.name}} - {{item.address}}
</li>
</ul>
</div>
Alternatively, you could make an extra field on your model for sorting.
function AppCtrl($scope) {
$scope.items = [
{'name':'NamedItem1','address':'1920', 'sortOrder': 1 },
{'name':'NamedItem2','address':'4192', 'sortOrder': 2 },
{'name':'NamedItem5','address':'2039', 'sortOrder': 5 },
{'name':'NamedItem45','address':'2090', 'sortOrder': 45 },
{'name':'NamedItem50','address':'1029', 'sortOrder': 50 },
{'name':'NamedItem100','address':'1829', 'sortOrder': 100 },
{'name':'NamedItem400','address':'1728', 'sortOrder': 400 }
];
}
And change your sort to look at this field.
<div ng-app>
<ul ng-controller="AppCtrl">
<li ng-repeat="item in items|filter:deviceBindingFilter|orderBy:'sortOrder'">
{{item.name}} - {{item.address}}
</li>
</ul>
</div>

Categories

Resources