Filtering in two different tabs (AngularJS) - javascript

I have two tabs and have to implement filtering on both of them.
In second tab everything works fine, but in first one not.
I'm filling that problem relates to this part(ng-model):
<ul search-list=".letter" model="search.district">
<li class="letter" ng-repeat="letter in alphabet.letter">{{ letter }}</li>
</ul>
and to this:
<input id="q" type="text" ng-model="search.district " />
So second tab works fine:
<div ng-repeat="district in districts | filter:search:startsWith" class="district">
<h4 class="district-name">{{ district.district }}</h4>
Some info
<ul class="district-cities">
<li ng-repeat="city in district.cities ">
<a href="{{ city.url }}">
{{ city.name }}
</a>
</li>
</ul>
</div>
But how to make works first part I don't know...
Here is DEMO

Do this changes in HTML
<div class="tab-content active" data-id="first">
<li ng-repeat='city in cities | filter:{name :search.district}:startsWith'>
<a href="{{ city.link }}">
{{ city.name }}
</a>
</li>
</div>
Here is the updatd Plunker

In your startsWith method you are specifically referencing the district property of the object. This property doesn't exist on city objects:
$scope.startsWith = function (actual, expected) {
var lowerStr = (actual + "").toLowerCase();
var e = angular.isString(expected) ? expected.toLowerCase() :
// district is not present in City object
expected.district.toLowerCase();
return lowerStr.indexOf(e) === 0;
}

Since you're using search.district, it tries to access the .district value for the cities.
You can use search.name instead, here...
<ul search-list=".letter" model="search.name">
...and here...
<input id="q" type="text" ng-model="search.name" />
and then rename district to name on each district of the district array.

Related

using template div id in an angular if statement

I have a modal with 3 lists that have unique ids:
<p class="accordion" ng-class"{active:accordion==2}" ng-click="accordion = 2">COPY from the PARCEL:</p>
<ul class="related_email_list accordion-content" ng-show="accordion==2">
<li ng-repeat="address in parcelAddressToStk">
<label for="selectAddress_parcel_{{address.AddressID}}">
<input type="checkbox" name="{{address.Alternate}}" class="parcelAddress" id="selectAddress_parcel_{{address.AddressID}}" value="{{address}}" ng-click="selectedAddresses(address);" ng-model="address.isSelected" ng-options="address.AddressID as address.pseudo for address in parcelAddressToStk" />
<span>
<b class="int-name">{{address.AddressType==='Mailing'?'Mailing Address:':(address.AddressType==='Street'?'Parcel Address:':(address.AddressType==='Mailing/Street'?'Mailing/Street Address:':'Home Quarter Address:'))}} </b>
<b>{{address.Alternate}}</b>
<b>{{address.StreetNumber?address.StreetNumber+" ":""}}{{address.StreetDirPre?address.StreetDirPre+" ":""}}{{address.StreetName?address.StreetName+" ":""}}{{address.StreetType?address.StreetType+" ":""}}{{address.StreetDirSuf?address.StreetDirSuf+" ":""}}{{address.UnitNumber!==""?"Unit " + address.UnitNumber:""}}</b>
<b>{{address.Municipality?address.Municipality+" ":""}}{{address.SubDivisionCode?address.SubDivisionCode+" ":""}}{{address.PCODE?address.PCODE+" ":""}}{{address.PostalZip?address.PostalZip+" ":""}}</b>
</span>
</label>
</li>
</ul>
I want to know if it's possible to use the selectAddress_parcel_{ID} in an if statement. I've tried
if ($scope["selectAddress_parcel_" + item.AddressID] == true) {
//do something
}
which comes back as undefined in the watch list. But if I hard-code selectAddress_parcel_56088 in watch I can see the correct object.
Is there an easier way to do this or am I concatenating my if statement incorrectly?

Angular Js ng-init is not working properly inside ng-repeat while setting a variable

I have a ng-repeat where i am checking a if condition and at the end of each repeation of loop i am setting a variable to a value from ng-repeat
Here is my variable which i want to set inside the ng-repeat
$scope.prvSid = "";
Here is my ng-repeat code
<ul class="chats" ng-repeat="chatData in chatboxData">
<li ng-class="{ 'out': chatData.sender_id == user_id , 'in': chatData.sender_id != user_id }">
{{ prvSid }}
{{ chatData.sender_id }}
<span ng-if=" prvSid != chatData.sender_id ">
<img class="avatar" alt="" src="{{ url('default/img/user_default_logo.jpg') }}" />
</span>
<div class="message">
<span class="body"> {{ chatData.message }} </span>
</div>
<span ng-init="prvSid = chatData.sender_id"></span>
{{ prvSid }}
</li>
</ul>
The problem which i am facing here is that whenever i print these values inside the ng-repeat then prvSid and chatData.sender_id is printing the same id the value of chatData.sender_id even for the first iteration and that's why this
<span ng-if=" prvSid != chatData.sender_id ">
condition is not working and my image is not displaying because for the first iteration the condition should be true because prvSid is "" and chatData.sender_id has some id in it
The purpose of this is to
Henry Zou the purpose is to not show profile picture for two or more messages submitted by same user (if the sender_id is same)Then dont display the profile image.When the new message comes from another sender which means sender_id is different then show the profile image
at first the prvSid will be null so it will show the image because condition will not match at the end of each iteration i will set the prvSid to the current iteration sender_id to match this prv_id with sender_id in the next iteration
i am also getting messages after two seconds and then i am adding the new records in the chatboxdata if they dont exist in it
$scope.getlasttwosecMsgs = function(user_id_chat,chat_id,user,chatboxData,is_new) {
$http.get(url+'/getlasttwosecMsgs/'+chat_id).success(function(data){
angular.forEach(data, function(value, key) {
var exists = $scope.containsObject(value,chatboxData);
if (!exists) {
$scope.chatboxData.push(value);
console.log($scope.chatboxData);
};
});
});
}
$scope.containsObject = function(obj, list) {
var i;
for (i = 0; i < list.length; i++) {
if (angular.equals(list[i], obj)) {
return true;
}
}
return false;
};
This new code snippet will check current userID against a list of users in the chatbox. For all users that's not the current user, show content.
approach #1 (preferred)
angular
.module('app', [])
.controller('myCtrl', function(){
var vm = this;
var prvSid = null;
vm.chatboxData = [{id:1},{id:1},{id:2},{id:3}];
vm.chatboxData.forEach(function(chatbox){
if(prvSid !== chatbox.id){
chatbox.showIcon = true;
}
prvSid = chatbox.id;
});
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
<div ng-app="app">
<div ng-controller="myCtrl as vm">
<ul class="chats" ng-repeat="chatData in vm.chatboxData">
<li>
<span ng-if="chatData.showIcon ">
ICON
</span>
{{::chatData.id}}
</li>
</ul>
</div>
</div>
approach #2
angular
.module('app', [])
.controller('myCtrl', function(){
var vm = this;
vm.prvSid = null;
vm.chatboxData = [{id:1},{id:1},{id:2},{id:3}];
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
<div ng-app="app">
<div ng-controller="myCtrl as vm">
<ul class="chats" ng-repeat="chatData in vm.chatboxData">
<li>
<span ng-if="chatData.showIcon ">
ICON
</span>
{{::vm.prvSid}} {{::chatData.id}}
<span ng-init="chatData.showIcon = (vm.prvSid !== chatData.id)"></span>
<span ng-init=" vm.prvSid = chatData.id"></span>
</li>
</ul>
</div>
</div>
approach #3 (without using controllerAs syntax)
angular
.module('app', [])
.controller('myCtrl', function($scope){
var prvSid = null;
$scope.chatboxData = [{id:1},{id:1},{id:2},{id:3}];
$scope.chatboxData.forEach(function(chatbox){
if(prvSid !== chatbox.id){
chatbox.showIcon = true;
}
prvSid = chatbox.id;
});
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
<div ng-app="app">
<div ng-controller="myCtrl">
<ul class="chats" ng-repeat="chatData in chatboxData">
<li>
<span ng-if="chatData.showIcon ">
ICON
</span>
{{::chatData.id}}
</li>
</ul>
</div>
</div>
OLD ANSWER
In the video AngularJS MTV Meetup: Best Practices (2012/12/11), Miško
explains "..if you use ng-model there has to be a dot somewhere. If
you don't have a dot, you're doing it
wrong.."
ng-repeat creates an inherited scope (think javascript prototype) for each item.
This code below will create $scope.prvSid for each item in the array and the value will always be chatData.sender_id.
<span ng-init="prvSid = chatData.sender_id"></span>
If you meant it to only have 1 instances of prvSid id, then what you'll need to do is initialize prvSid variable at the parent scope first (or use the dot(.) rule)
<div ng-init="prvSid = null"> <!-- initializing prvSid id # parent scope -->
<ul class="chats" ng-repeat="chatData in chatboxData">
<li ng-class="{ 'out': chatData.sender_id == user_id , 'in': chatData.sender_id != user_id }">
{{ prvSid }}
{{ chatData.sender_id }}
<span ng-if=" prvSid != chatData.sender_id ">
<img class="avatar" alt="" src="{{ url('default/img/user_default_logo.jpg') }}" />
</span>
<div class="message">
<span class="body"> {{ chatData.message }} </span>
</div>
<!-- this will now update the parent scope's prvSid instead of creating a new one for each item in the array -->
<span ng-init="prvSid = chatData.sender_id"></span>
{{ prvSid }}
</li>
</ul>
</div>

Angular Checkbox Filter with Paginator

I'm using this AngularJS paginator, https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination.
And I'm also using the example in this video to add checkbox filters to my ng-repeat. I want to filter based on whether the specie property of every animal object (animal.specie) is a cat or a dog. I start setting both to true but my ng-repeat doesn't populate when I do that. And when I check a box to true or false nothing happens.
The only thing in the controller is $scope.species = {dogs: true, cats: true};
What is wrong with my implementation? Any help will be much appreciated.
Thanks :)
<div class="row adopt-title-wrap">
<div class="medium-6 large-6 column">
<h3>Find Your Next Best Friend</h3>
</div>
<div class="medium-2 large-2 end column">
<input type="checkbox" ng-model="species.cats">
<label>Cats Only</label>
</div>
<div class="medium-2 large-2 end column">
<input type="checkbox" ng-model="species.dogs">
<label>Dogs Only</label>
</div>
</div><br>
<i class="fa fa-spinner fa-pulse fa-3x"></i>
<div class="row">
<!-- Start Single Animal Record -->
<div class="medium-6 large-6 end column" dir-paginate="animal in animals
| filter: {specie: 'Dog'} : species.dogs
| filter: {specie: 'Cat'} : species.cats
| itemsPerPage: 6">
<div class="panel">
<img class="pet-img" ng-src="{{ animal.profile_photo }}" alt="pet for adoption">
<ul class="pet-details">
<li class="pet-field-title">Name</li>
<li class="pet-field-value">{{ animal.name }}</li>
<li class="pet-field-title">Age</li>
<li class="pet-field-value">{{ animal.dob }}</li>
<li class="pet-field-title">Breed</li>
<li class="pet-field-value">{{ animal.breed }}</li>
<li class="pet-field-title">Code</li>
<li class="pet-field-value">{{ animal.shelter_code }}</li>
</ul>
<p class="pet-description">{{ animal.description }}</p>
</div>
</div> <!-- End Single Animal Record -->
</div>
<dir-pagination-controls></dir-pagination-controls>
I would recommend stripping down your code to the base, maybe just get everything displayed and then migrate to pagination. I can spot your first issue is you are applying two filters on specie.
dir-paginate="animal in animals | filter: {specie: 'dog'} | filter: {specie: 'cat'}"
is basically saying filter down to animals that are both a dog and a cat. The first filter will return an array of only dogs, then the second filter will run on that finding only cats, which is none because obviously you can't be a dog and a cat :)
Original Array: [{name: 'bob', specie: 'cat'}, {name: 'jeff', specie: 'dog'}] | filter dogs | filter cats
After First Filter (only dogs): [{name: 'jeff', specie: 'dog'}] | filter cats
After Second Filter (only animals that are both dogs and cats): []
Try defining your own angular filter to simplify your work as so:
.filter('isCatOrDog', function() {
return function(inputAnimals) {
return inputAnimals.filter(function(animal) {
return animal.value === 'cat' || animal.value === 'dog';
});
}
});
And you call the filter as so:
dir-paginate="animal in animals | isCatOrDog"
Basic Plunkr
Just learned that Angular filters don't have (at least not yet) the functionality I was looking for. So I worked around the issue by changing the check boxes to radio buttons and make a different backend API call based on the radio selected.
template:
<div class="row adopt-title-wrap">
<div class="medium-5 large-5 column">
<h4>Find Your Next Best Friend!</h4>
</div>
<div class="medium-1 large-1 column">
<i class="fa fa-spinner fa-pulse fa-2x"></i>
</div>
<div class="medium-2 large-2 column">
<input type="radio" ng-model="species" value="all">
<label>Show All</label>
</div>
<div class="medium-2 large-2 column">
<input type="radio" ng-model="species" value="cats">
<label>Cats Only</label>
</div>
<div class="medium-2 large-2 column end">
<input type="radio" ng-model="species" value="dogs">
<label>Dogs Only</label>
</div>
</div>
<div class="row">
<!-- Start Single Animal Record -->
<div class="single-record medium-6 large-6 end column" dir-paginate="animal in animals | itemsPerPage: 6">
<div class="panel">
<img class="pet-img" ng-src="{{ animal.profile_photo }}" alt="pet for adoption">
<ul class="pet-details">
<li class="pet-field-title">Name</li>
<li class="pet-field-value">{{ animal.name }} ({{animal.specie }})</li>
<li class="pet-field-title">Age</li>
<li class="pet-field-value">{{ animal.dob }}</li>
<li class="pet-field-title">Breed</li>
<li class="pet-field-value">{{ animal.breed }}</li>
<li class="pet-field-title">Code</li>
<li class="pet-field-value">{{ animal.shelter_code }}</li>
</ul>
<p class="pet-description">{{ animal.description }}</p>
</div>
</div> <!-- End Single Animal Record -->
</div>
<dir-pagination-controls></dir-pagination-controls>
Controller:
angular.module('animalShelterApp')
.controller('AdoptCtrl', function ($scope, SharedServices) {
var spinner = angular.element('.fa-spinner'); // Holds spinner element.
/*
* Binds 3 radio buttons (all, cats, dogs).
* Load 'all' records by default.
*/
$scope.species = 'all';
/*
* When user selects a specie, display appropriate data.
*/
$scope.$watch('species', function() {
spinner.show();
if ($scope.species === 'all') {
/*
* Get all available animals.
*/
SharedServices.getAllAnimals().success(function(data) {
spinner.hide();
$scope.animals = data;
});
} else if ($scope.species === 'cats') {
/*
* Get all available Cats.
*/
SharedServices.getAllCats().success(function(data) {
spinner.hide();
$scope.animals = data;
});
} else if ($scope.species === 'dogs') {
/*
* Get all available Dogs.
*/
SharedServices.getAllDogs().success(function(data) {
spinner.hide();
$scope.animals = data;
});
}
}); // end $scope.$watch('species').
}); // end AdoptCtrl.

Having trouble repeating correct items with nested ng-repeat and ng-if

I have the following html:
<div ng-repeat="tab in tabs" ng-if="tabIsActive(tab, $index)">
<ul ng-repeat="section in tab.sections">
<h2 ng-class="productTitle" ng-repeat="child in section.children" ng-if="sideTabIsActive(section, $index)">
<img ng-src="{{ child.productImageURL }}"/>
<li>{{ child.title }}</li>
</ul>
</div>
This is what the "tabs" javascript object looks like:
My desired output is the subcategory titles(e.g. children0.title) and image(e.g. children0.productImageURL) listed for each section when that section is selected.
Example desired output:
When Analytical Balances is clicked
(ML image) //which is section0.child0.productImageURL
ML //which is section0.child0.title
(XS image) //which is section0.children1.productImageURL
XS //which is section0.child1ren.title
Currently, I display this:
When Analytical Balances is clicked:
(ML image) //which is section0.children0.productImageURL
ML //which is section0.children0.title
(XPE image) //which is section1.children0.productImageURL
XPE //which is section1.children0.title
How can I list both children (and the associated image) for each section based on which section is selected (selectedSideIndex)?
In addition to the above HTML, here is relevant HTML and javascript that I use in my attempt to achieve the desired output:
$scope.toggleSideSelect = function(ind){
$scope.selectedSideIndex = ind;
}
$scope.sideTabIsActive = function (tab, $index) {
var selectedIndexTest = $scope.selectedSideIndex
return $index==$scope.selectedSideIndex;
}
<div ng-repeat="tab in tabs" ng-if="tabIsActive(tab, $index)">
<ul ng-repeat="section in tab.sections" ng-click="toggleSideSelect($index)">
<li>{{ section.title }}</li>
<ul ng-repeat="child in section.children">
<li>{{ child.title }}</li>
</ul>
</ul>
</div>
You were almost there :)
What you need to do is this:
<div ng-repeat="tab in tabs" ng-if="tabIsActive(tab, $index)">
<ul ng-repeat="section in tab.sections" ng-init="sectionIndex = $index">
<h2 ng-class="productTitle" ng-repeat="child in section.children" ng-if="sideTabIsActive(section, sectionIndex)">
<img ng-src="{{ child.productImageURL }}"/>
<li>{{ child.title }}</li>
</ul>
</div>
This way, using the ng-init="sectionIndex = $index" you are saving the $index of the section and can use it on the nested ng-repeat. It's also possible to use $parent.$index but I wouldn't recommend it since the structure might change and you will be left with a bug.
This way, you can call ng-if="sideTabIsActive(section, sectionIndex)" using the index of the section, and only your active section's children will get to show.
Edit: you should probably change the signature of
$scope.sideTabIsActive = function (tab, $index)
to
$scope.sideTabIsActive = function ($index)
Since you're not actually using the tab in the function. (And if you do, don't forget to change the call to that function from the view as well)

AngularJS filter ng-repeat based on value from scope

I want to display all data (contacts) that have bookmarked value set to 1
To do that I used this peace of code:
<ul class="span5">
<li class="nav-pills nav-stacked contact-row" data-ng-repeat="contact in contacts | orderBy:'firstName'" ng-show="contact.bookmarked('0')">
<span id=" ct-details-{{contact.id}}" data-ng-click="displayContact(contact.id)" style="cursor:pointer;" class="contact-data details-hidden" href="">
<span class="span3 contact-name">
{{contact.firstname + ' ' + contact.lastname}}
</span>
</span>
<button class="btn editContact" id="deleteContact-{{contact.id}}" data-ng-click="deleteContact(contact.id)">Delete</button>
<button class="btn editContact" id="editContact-{{contact.id}}" data-ng-click="editContact(contact.id)">Edit</button>
</li>
</ul>
When I use this code, contacts are not displayed (ones with value 1 and ones with value 0 are not displayed). Does someone knows where's the problem and how to fix it?
You should create a filter on your ngRepeat query.
data-ng-repeat="contact in contacts | filter:{bookmarked:'0'} | orderBy:'firstName'"
Read more about here: https://docs.angularjs.org/api/ng/filter/filter

Categories

Resources