Angular JS Filter Reverse - javascript

Using this angular JS feature in angular is it possible to not display the results on page load?
But when a user types in the search box then the filtered results appear?
See link for the feature in using:
https://docs.angularjs.org/api/ng/filter/filter
This appears to be what I'm after but I'd rather the results on page load didn't show.
Here's my code:
$scope.members = Members.query({key:$scope.Key}); //Grabs Json from API, can confirm results do come through.
$scope.myFilter = function(obj) {
if (!$scope.searchText)
return false;
else
return obj.first_name.toLowerCase().indexOf($scope.searchText.toLowerCase()) > -1;
}
My HTML
<div class="list">
<div class="item">
<input type="text" ng-model="searchText">
</div>
<div ng-repeat="m in members | filter:myFilter" class="item item-button-right">
{{ m.first_name | limitTo: 1 }}{{m.first_name.length > 1 ? '. ' : ''}}{{m.last_name}}
</div>
</div>

If you know what is going to be in the search box before the user changes the content then you could hide the result element when it is matching that value. So you could do:
<div ng-hide="searchInput === 'my search'"></div>

Related

Using multiple ids get text from element that is visible

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.

Target only 1 button in Angular

Im getting the values in a div from the DB and displaying using ng-repeat:
<div ng-controller = "myTest">
<div ng-repeat="name in names">
<h4>{{name.name}}</h4>
<button ng-class="{'active': isActive}" ng-click="test()" >me</button>
</div>
</div>
In my controller I have:
$scope.test= function(){
$scope.isActive = !$scope.isActive;
}
I have defined a class isActive in my css and that is applied/removed to the button on click. There are 5 results so 5 divs are created cause of ng-repeat and 5 buttons(1 for each respective div). The problem is that every button (all 5 of them) is getting that class. I want the class to be applied/removed only to the button clicked. How can I achieve this?
You can try something like this :
<div ng-controller="myTest">
<div ng-repeat="name in names">
<h4>{{name.name}}</h4>
<button ng-class="{ active : name.isActive }"
ng-click="name.isActive = !name.isActive">me</button>
</div>
</div>
Hope this will help.
You need to keep track of each button status.
One way will be to passing the name or anything that uniquely identify the button to your function:
<div ng-controller = "myTest">
<div ng-repeat="name in names">
<h4>{{name.name}}</h4>
<button ng-class="{'active': buttons[name].isActive}" ng-click="test(name)" >me</button>
</div>
</div>
$scope.buttons = {};
$scope.test= function(name){
$scope.buttons[name].isActive = !$scope.buttons[name].isActive;
}
I created a plunk that answers this question without modifying your source array.
Your function becomes
vm.test = function(buttonIndex) {
//Clear the class if you press the same button again
if (vm.buttonIndex === buttonIndex) {
vm.buttonIndex = undefined;
} else {
vm.buttonIndex = buttonIndex;
}
};
And your HTML is
<div ng-repeat="name in main.names track by $index">
<h4>{{name.name}}</h4>
<button ng-class="{'active': main.buttonIndex===$index}" ng-click="main.test($index)">me</button>
</div>

How to know if AngularJS filtered and limited lists lengths are the same

I'm trying to show an alert in case a filtered and limited list has elements not being shown. I'm looking for a good performing solution, as these lists will be really long.
Here is what I have from now:
<div class="list_item" ng-repeat="item in $ctrl.list | filter: $ctrl.responsiveFilter | limitTo: 6 as results track by $index">
<label ng-click="$ctrl.handle_list_click()">
<input type="checkbox" ng-model="item.checked">
<div class="fake_label" >
{{item.name}}
</div>
</label>
</div>
<div class="list_item too_many"
ng-repeat-end
ng-if="results.length > 6">
<div class="fake_label">
{{results.length}} matches... Please, filter out.
</div>
</div>
But the results contains the elements after being filtered and also limited. If I move the as results just before the limitTo, it just breaks.
The condition I want to detect show the alert would be: if the limited list's length and the filtered list's length are different, then show the alert.
I don't mind using something else, instead of the as results, just wonder if there is a way to detect that condition.
Edit: the problem right now is that results.length gives me the amount of elements after applying the limit, while what I need is the amount just after the filter, but before the limit. I know how to do this by deleting the limitTo sentence, but then there are too many results on the list...
var newapp = angular.module('someapp',[]);
newapp.service('limitcheck', [function(){
return {
checkLimit : function (arr) {
if (arr.length > 6) {
alert('The array has more than 6 entries');
}
}
};
}]);
newapp.filter('dummyfilter',['limitcheck',function(limitcheck){
return function (input) {
//do your filtering here
limitcheck.checkLimit(input);
return input;
}
}]);
newapp.controller('something', ['$scope',function(scope){
//This will trigger alert since it contains more than 6 entries
scope.alist = ['me','you','someone','anyone', 'noone','everyone','villain'];
//this will not
//scope.alist = ['me','you','someone','anyone', 'noone','everyone'];
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='someapp'>
<div ng-controller='something'>
<div ng-repeat='person in alist | dummyfilter | limitTo :6'>
{{person}}
</div>
</div>
</div>
I have tried and achieved the result by using a service and a filter combination
I hope this helps
The easiest way is to duplicate the repeat and use it to count the filtered elements. At first, I expected this to be quite slow but I'm really surprised of how fast it runs, probably because there is not really much DOM manipulation.
<div class="list_item" ng-if="false" ng-repeat="item in $ctrl.list | filter: $ctrl.responsiveFilter as count track by $index">
</div>
<div class="list_item" ng-repeat="item in $ctrl.list | filter: $ctrl.responsiveFilter | limitTo: 6 as results track by $index">
<label ng-click="$ctrl.handle_list_click()">
<input type="checkbox" ng-model="item.checked">
<div class="fake_label" >
{{item.name}}
</div>
</label>
</div>
<div class="list_item too_many"
ng-repeat-end
ng-if="count.length > results.length">
<div class="fake_label">
{{count.length}} matches... Please, filter out.
</div>
</div>
This way you have an ng-if hidden loop to count the filtered elements and another one to count and paint the limited list. All you have to do is to use these data to create the condition.

I have a 100 button, click each button to display its corresponding bomb box, With javascript and angular

a button corresponding to a prompt box,each box is different shells;Although implements the desired function, but my code is too complicated, and that there is no simple way. how can I do? This is my code
<--html button-->
button1
button2
...
button100
<--html pop box-->
<div class="note1" style="display:none;">
<img class="title-css" src="note1.png">
<p class="one">note1</p>
</div>
...
<div class="note100" style="display:none;">
<img class="title-css" src="note100.png">
<p class="one">note100</p>
</div>
<--angular js-->
$scope.showRulePop = function(index) {
for(var i=1;i<=8;i++) {
$('.note'+i).hide();
}
$('.note'+index).show();
};
Well first of all, don't use jQuery, unless your in the directive level of angular jQuery have nothing to do there.
First let's get rid of the links part using a simple ng-repeat :
<--html button-->
<div ng-repeat="button in buttons">
{{button.label[i]}}
</div>
// JS in the controller
$scope.buttons = [{
label:'button1'
},{label:'button2'}];
As you can see i declare in the javascript all your buttons and i just loop over it.
Now the "bombox" or whatever it is let's make it a simple template :
<div class="{{currentnote.class}}" ng-if="currentNote">
<img class="title-css" src="{{currentNote.img}}">
<p class="one">{{currentNote.content}}</p>
</div>
// and use ng-repeat for the eight first when there is no button selected
<!-- show 1 to 8 if note current note selected -->
<div ng-repeat="button in buttons1To8" ng-if="!currentNote">
<div class="{{button.note.class}}">
<img class="title-css" src="{{button.note.img}}">
<p class="one">{{button.note.content}}</p>
</div>
</div>
// JS
$scope.buttons = [{
label:'button1'
note:{class:'note1', img:'note1.png', content:'note1'//assuming no HTML or you' ll need something more
}},{label:'button2', note:{...}}, ...];
$scope.showRulePop = function(index){
$scope.currentNote = $scope.buttons[index].note;
}
$scope.buttons1To8 = $scope.buttons.slice(0, 8);//0 to 7 in fact
That's all, no need of jQuery.

jQuery pass dynamically created variable to another function

I have form partial in Rails, laid out like so:
<div class"row">
<div class="col-md-6" id="top_level">
</div>
</div>
<div class"row">
<div class="col-md-2" id="sub_category1">
</div>
</div>
<div class"row">
<div class="col-md-2" id="sub_category2">
</div>
</div>
<div class"row">
<div class="col-md-2" id="sub_category3">
</div>
</div>
<div class"row">
<div class="col-md-3" id="sub_category4">
</div>
</div>
<div class"row">
<div class="col-md-3" id="sub_category5">
</div>
</div>
It is for selecting categories and sub-categories of items.
listings_controller:
def new
#product_listing = Listing.new
#product_ = Product.find(params[:product_id])
# gon.categories = EbayCategory.all
gon.top_level = EbayCategory.top_level
end
In the model:
scope :top_level, -> { where('category_id = parent_id').order(:id) }
Each category record (17989 of them) has a unique category_id, and a parent_id. As indicated above, the top level category_id = the parent_id for the same record. All the subcategories have their own category_ids, which are the parent_ids of the next level down, and so on, varying between 1 and 5 sub-levels.
I've tried a cascade of view files, which works fine (it renders the correct categories and sub-categories) but I can't pass the listing id that way because I don't know how to transmit 2 ids (one for the parent category, one for the listing id) through the params hash using the link_to url helper, so I lose the id for the listing I'm trying to create while navigating all the sub-categories.
So I'm trying it with jQuery, using the Gon gem. Not only does this mean loading the entire db table (about 7 MB, once I un-comment the line for use in level 2 thru 5) into ram, but I can't figure out how to pass the category_id from the dynamically created top_level list when one of its elements is clicked. There are many levels to go, but right now I'm just trying to console.log the category_id for ONE level, so I can see that it's registering. So far unsuccessful, after trying many different syntaxes and methods, of which this is the latest:
<script type="text/javascript">
$(gon.top_level).each(function(){
$("#top_level").append('<h5>' + this.main_category + " >" + '</h5>').data($(this).category_id);
})
$("#top_level").on('click', 'a', function(){
console.log($(this).data());
});
</script>
...returns
Object {}
to the console.
Any suggestions on how to store ids dynamically with the text category titles?
$('gon.top_level').each(function(){
var lnk = $('<h5>' + this.main_category + " >" + '</h5>')
.find('a').data({'category':$(this).category_id,'anotherKey':'value'});
$("#top_level").append(lnk);
});
$("#top_level").on('click', 'a', function(){
console.log($(this).data('category'));
console.log($(this).data('anotherKey'));
});
To set data use $(elment).data({key:value});
To get data use $(elment).data(key);

Categories

Resources