Show {{ value }} except special one in AngularJS 1.6 - angularjs

After SPAN click my DIV get this category title , but in one case , when category.title is 'Favorite' (or category.id = '1',its the same) i need ignore it in DIV and don't change the value on it.
How can i realize that ?
Thanks in advance
My HTML :
<div> {{ selections.category.title }} </div>
<span ng-repeat="category in categories track by category.id" ng-click="selectCategory(category)">
...
</span>
My controller :
$scope.selectCategory = function selectCategory(category) {
$scope.selections.category = category;
...
}
EDIT.
I need only ignore it in DIV's text , not ignore click on this element .

<div> {{ selectedTitle }} </div>
$scope.selectCategory = function selectCategory(category) {
if(category.title !== 'Favorite' && category.id !== '1') {
$scope.selectedTitle = category.title;
}
$scope.selections.category = category;
...
}

Related

Vue Show more in deep array

I am trying to add a "show-more" button to an array(v-for) of an array (v-for).
<li v-for="(recruiter, key) in recruiters.data" :key="recruiter.id">
<div v-if="recruiter.cities" >
<div v-if="recruiter.cities.length <= 5 || recruiter.id in cities_expand">
<a :href="'/rekryterare/' + city.slug" v-for="(city, index) in recruiter.cities">{{ city.name }}</a>
</div>
<div v-else>
<template v-for="(city, index) in recruiter.cities">
<template v-if="index+1 <= 4">
<a :href="'/rekryterare/sverige/' + city.slug" >{{ city.name }}</a>
</template>
</template>
<a href="#" #click.prevent="cities_expand.push(recruiter.id)" >...</a>
</div>
</div>
</li>
Basically if there is more than 4 items in recruiter.cities -> show 4 items + "show more"
However - the recruiter.id in cities_expand does not work/update?
I'm sure there is a better way of solving this - but nothing else came to mind :)
Any ideas?
I'm suspect that the problem is the use of the js in operator. The in operator checks if an object has a key in the object. It does not check if an array has a value.
So when doing recruiter.id in cities_expand, this checks if recruiter.id is a key in the array cities_expand. The keys of an array are the array indices.
This would explain why spam clicking will work because if the recruiter.id is e.g. 9, then recruiter.id in cities_expand will only be true if cities_expand has key 9 i.e. length 10. Which means you would have to click ... 10 times.
Changing
<div v-if="recruiter.cities.length <= 5 || recruiter.id in cities_expand">
to
<div v-if="recruiter.cities.length <= 5 || cities_expand.indexOf(recruiter.id) > -1 ">
should do the trick.
In terms of an alternative solution, I would encapsulate the inner loop in a component and use a computed value for the list. E.g.
Component RecruiterCities:
<template>
<div v-if="displayCities" >
<a :href="'/rekryterare/' + city.slug" v-for="(city, index) in displayCities" :key="index">{{ city.name }}</a>
<a v-if="!showExpanded && totalCities > maxDisplayCities" href="#" #click.prevent="showExpanded = true" >...</a>
</div>
</template>
<script>
export default {
props: {
recruiterCities: {
type: Array,
default() {
return []
}
}
},
data() {
return {
showExpanded: false,
maxDisplayCities: 4
}
},
computed: {
totalCities() {
return (this.recruiterCities && this.recruiterCities.length) || 0;
},
displayCities() {
if (!this.recruiterCities) {
return [];
}
if (this.showExpanded || this.recruiterCities.length <= this.maxDisplayCities) {
return this.recruiterCities;
}
return this.recruiterCities.slice(0, this.maxDisplayCities);
}
}
}
</script>
and to use it:
<li v-for="(recruiter, key) in recruiters.data" :key="recruiter.id">
<RecruiterCities :recruiter-cities="recruiter.cities"/>
</li>

Issue with Ngfor only supports binding to Iterables such as Arrays

error
supporting object 'Active' of type 'string'. NgFor only supports binding to Iterables such as Arrays.
I was trying to make it where every time i click the toggle it will change the {{ setting }} from Inactive to active. was trying to get this method working if the other one fails to be possible.
code html:
<ion-item>
<ion-label>Front Door</ion-label>
<ion-toggle [(ngModel)]="fdoor" ng-model="ni_toggle" (ionChange)="Fdoor()" (click)="change()"></ion-toggle>
</ion-item>
<div *ngFor="let setting of sett">
{{ setting }}
</div>
ts:
active: string = "Active"
inactive: string = "Inactive"
change() {
if(this.fdoor = true) {
this.sett = this.active
}
}
I don't know what is your purpose. But I think you should do like this:
sett = false;
change() {
if(this.fdoor = true) {
this.sett = !this.sett;
}
}
HTML
<ion-item>
<ion-label>Front Door</ion-label>
<ion-toggle [(ngModel)]="fdoor" ng-model="ni_toggle" (ionChange)="Fdoor()" (click)="change()"></ion-toggle>
</ion-item>
<div>
{{ sett ? "Active" : "Inactive" }}
</div>

when ng-repeat list of folders updates wrong

I have receive listof objects with names: F1,F2,F3,F4
when I make call to server, I receive new list F1,F2,F3,F5,F4
when I apdate ng-repeat list:
vm.folders = data.content.items;
it shows next list: F1,F2,F3,F4,F4
where am I wrong? here is my html code:
<div ng-repeat="folder in vm.folders track by $index" ng-init="openInput=false;">
<div layout="row" ng-init="folderName = vm.getIterationName(folder.metadata)" >
<div >
</div>
<div >
<span ng-click="showChildren[$index]=!showChildren[$index]" class="capitalize" ng-dblclick="openInput = true;$event.stopPropagation();" ng-show="!openInput">{{folderName}}</span>
</div>
</div>
</div>
js update method:
function updateIterations(data) {
if (data.ok === true) {
if(angular.toJson(vm.folders) != angular.toJson(data.content.items)) {
vm.folders = data.content.items;
}
} else if (data.ok == false) {
console.log ('Error:iteration request: {ok: false}');
$interval.cancel(intervalRequests);
}
}
fixed!
in
<span ng-click="showChildren[$index]=!showChildren[$index]" class="capitalize" ng-dblclick="openInput = true;$event.stopPropagation();" ng-show="!openInput">{{folderName}}</span>
instead of {{folderName}} i've used:
<span ng-click="showChildren[$index]=!showChildren[$index]" class="capitalize" ng-dblclick="openInput = true;$event.stopPropagation();" ng-show="!openInput">{{vm.getIterationName(folder.metadata)}}</span>

Preprocess ng-repeat variables?

I am using ng-repeat to print the output in div. Elements in bCrumbs collection start with slash and space and I want to remove them from 1st loop iteration.
My Code:
<div ng-repeat="bCrumb in bCrumbs" id="{{bCrumb.name}}">{{ bCrumb.name }}</div>
the output from {{ bCrumb.name }}:
/ Test1
/ Test2
expected Output:
Test1
/Test2
You can use ng-repeat-start and ng-repeat-end
<div ng-repeat-start="bCrumb in bCrumbs" ng-if="$first>
{{ beautify(bCrumb.name) }}
</div>
<div ng-repeat-end ng-if="!$first">
{{ bCrumb.name }}
</div>
Besides, define a function called beautify in your controller:
$scope.beautify = function (name) {
return name.replace('/ ', '');
};
You can read the detailed documentation here
update
A better way to handle string beautify is creating a filter to handle it
app.filter('beautify', function () {
return function (data) {
return data.replace("/ ", "");
};
});
Then in your view template:
<div ng-repeat-start="bCrumb in bCrumbs" ng-if="$first>
{{ bCrumb.name | beautify }}
</div>
<div ng-repeat-end ng-if="!$first">
{{ bCrumb.name }}
</div>
I think you should change your controller (or whatever is producing bCrumbs) to strip the slashes before reaching view. This way it'll be more testable and (hopefully) clear. You could do something like this:
function strip(s) {
if(s.indexOf('/ ') === 0) {
return s.substring(2);
} else {
return s;
}
}
$scope.bCrumbs = originalBCrumbs.map(function(bc, idx) {
return idx === 0 ? strip(bc) : bc;
});

how get the list of selected items in angular.js

Here I am using angular.js to show a list of people
<div class="recipient" ng-repeat="person in people">
<img src="{{person.img}}" /> person.name
<div class="email">person.email</div>
</div>
$scope.people = [{id:1}, {id:2}, {id:3}, {id:4}];
The looks is like below
What I want to do is I can select multiple items and by click a OK button, I can get a list of selected items. so If I select id 1 and id 2, then I want to get return a list of [{id:1},{id:2}]
How could I implement it in angular.js
Well I guess that if you're looping through a collection of people using a ng-repeat, you could add the ng-click directive on each item to toggle a property of you're object, let's say selected.
Then on the click on your OK button, you can filter all the people that have the selected property set to true.
Here's the code snippet of the implementation :
<div class="recipient" ng-repeat="person in people" ng-click="selectPeople(person)">
<img src="{{person.img}}" /> person.name
<div class="email">person.email</div>
</div>
<button ng-click="result()">OK</button>
function demo($scope) {
$scope.ui = {};
$scope.people = [{
name: 'Janis',
selected: false
}, {
name: 'Danyl',
selected: false
}, {
name: 'tymeJV',
selected: false
}];
$scope.selectPeople = function(people) {
people.selected = !people.selected;
};
$scope.result = function() {
$scope.ui.result = [];
angular.forEach($scope.people, function(value) {
if (value.selected) {
$scope.ui.result.push(value);
}
});
};
}
.recipient {
cursor: pointer;
}
.select {
color:green;
}
.recipient:hover {
background-color:blue;
}
<script src="https://code.angularjs.org/1.2.25/angular.js"></script>
<div ng-app ng-controller="demo">
<div class="recipient" ng-repeat="person in people" ng-click="selectPeople(person)" ng-class="{ select: person.selected }">
<div class="name">{{ person.name }}</div>
</div>
<button ng-click="result()">OK</button>
Result :
<ul>
<li ng-repeat="item in ui.result">{{ item.name }}</li>
</ul>
</div>
If you only want to show checked or unchecked you could just apply a filter, but you would need to toggle the filter value from undefined to true if you didn't wan't to get stuck not being able to show all again.
HTML:
<button ng-click="filterChecked()">Filter checked: {{ checked }}</button>
<div class="recipient" ng-repeat="person in people | filter:checked">
<input type='checkbox' ng-model="person.isChecked" />
<img ng-src="{{person.img}}" />{{ person.name }}
<div class="email">{{ person.email }}</div>
</div>
Controller:
// Apply a filter that shows either checked or all
$scope.filterChecked = function () {
// if set to true or false it will show checked or not checked
// you would need a reset filter button or something to get all again
$scope.checked = ($scope.checked) ? undefined : true;
}
If you want to get all that have been checked and submit as form data you could simply loop through the array:
Controller:
// Get a list of who is checked or not
$scope.getChecked = function () {
var peopleChkd = [];
for (var i = 0, l = $scope.people.length; i < l; i++) {
if ($scope.people[i].isChecked) {
peopleChkd.push(angular.copy($scope.people[i]));
// Remove the 'isChecked' so we don't have any DB conflicts
delete peopleChkd[i].isChecked;
}
}
// Do whatever with those checked
// while leaving the initial array alone
console.log('peopleChkd', peopleChkd);
};
Check out my fiddle here
Notice that person.isChecked is only added in the HTML.

Resources