Angular filter only on button click - javascript

I can't seem to get my filter to only execute on a button click, it executes the first time and then filters automatically based on whatever text is in the box. Can someone help me out?
<section class="searchField">
<input type="text" ng-model="searchTerm">
<button type="button" ng-click="search()">Search</button>
</section>
<section ng-show="!resultsHidden">
<div class="no-recipes" ng-hide="players.length">No results</div>
<article class="playerSearch" ng-repeat="player in players | filter: filter" ng-cloak>
<h2>
{{player.name}}
</h2>
</article>
</section>
Javascript:
$scope.myFilter = function (player) {
var found = [];
for(player in players) {
if (player.name === $scope.searchTerm || player.number === $scope.searchTerm){
found.push(player);
}
}
return found;
};
function search(){
$scope.filter = $scope.searched;
$scope.resultsHidden = false;
}
$scope.searched = function(player){
if (!$scope.searchTerm || (player.number == $scope.searchTerm || (player.name.toLowerCase().indexOf($scope.searchTerm.toLowerCase()) != -1))){
return true;
}
return false;
};

var app = angular.module("app",[])
app.controller('ctrl',['$scope', function($scope){
$scope.resultsHidden = false;
$scope.players = [
{"name": "alpha"},
{"name": "beta"},
{"name": "gama"}
];
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<section class="searchField">
<input type="text" ng-model="searchTerm">
<button type="button" ng-click="filter = searchTerm;resultsHidden = !resultsHidden">Search</button>
</section>
<section ng-show="resultsHidden">
<div class="no-recipes" ng-hide="players.length">No results</div>
<article class="playerSearch" ng-repeat="player in players | filter:{name:filter}" ng-cloak>
<h2>
{{player.name}}
</h2>
</article>
</section>
</div>
try this
<button type="button" ng-click=" filter = searchTerm">Search</button>

First of all, you should create the filter like this:
angular.module('myApp')
.filter('my-filter', function( /* dependencies goes here */ ){
return function (input, isFilterActive) {
if (isFilterActive){
// filter your data
// your list will go into 'input' variable
// return filtered list
}
return input; //return data unfiltered;
}
});
And your html should look something like this:
<p ng-repeat="x in subcategories | my-filter:isFilterActive">
{{x.text}}
</p>
Where 'isFilterActive' variable can be placed on $scope. If 'isFilterActive' is true, your list will be filtered.
You can create a button that changes the value of it.
You can also check angular filters for more details or this tutorial: https://scotch.io/tutorials/building-custom-angularjs-filters
Have fun.

Related

Remove specific data from firebase using Angularjs

I'm trying to remove specific data from firebase using angularjs. But my coding removes all data from it. Any Help would be Appreciated.
For Example i need to delete the second data as highlighted using the remove button in it.
My HTML:
<div class="container" ng-controller="budgetCtrl">
<div class="row list" ng-repeat="kasu in panam">
<div class="col-6"> {{ kasu.title }} </div>
<div class="col-6 text-right total">
{{ kasu.spent | currency:"₹" }}
<button type="button" ng-click="deleteSpent(panam)">Remove</button>
</div>
</div>
<div class="row" style="background: #1feb6b">
<div class="col-6"> Total Money spend </div>
<div class="col-6 text-right"> {{ getTotal() | currency:"₹" }} </div>
</div>
</div>
My JS:
var nombre = angular.module('nombre', ['ngRoute', 'firebase']);
nombre.controller('budgetCtrl', ['$scope', 'money', '$firebaseObject', function($scope, money, $firebaseObject){
money.then(function(data){
$scope.cash = data;
});
var ref = firebase.database().ref();
$scope.panam = $firebaseObject(ref);
$("#nombre").submit(function() {
if( (!$("#Spentfor").val()) || (!$("#SpentAmount").val()) ) {
$(".form-control").css({"border":"3px solid red"});
}
else {
$(this), console.log("Submit to Firebase");
var Spentfor = $("#Spentfor").val(),
SpentAmount = $("#SpentAmount").val(),
total = { title: Spentfor, spent: SpentAmount};
return ref.push().set(total).then(function() {
$("#Spentfor, #SpentAmount").val("");
});
}
});
$scope.getTotal = function(){
var total = 0;
$scope.panam.forEach(p => {
total += parseFloat(p.spent);
});
return total;
}
$scope.deleteSpent = function(info){
$scope.panam
.$remove(info)
.then( function(ref){}, function(error){})
}
}]);
On Above JS i'm trying to delete specific data in firebase using deleteSpent() function. I know that i'm missing to targeting the specific data in my JS. If somebody helps me to solve and understand its concept would be appreciated.

How update list in AngularJS?

I created one TODO List in AngularJS but I didn't finish the update function. I have some difficulty.
How do I create the update function?
Link: https://plnkr.co/edit/XfWoGVrEBqSl6as0JatS?p=preview
<ul class="list-todo">
<li ng-repeat="t in tasks track by $index">
<div class="row">
<div class="six columns">
<p>{{ t }}</p>
</div>
<div class="three columns">
<button class="button" ng-click="update()">update</button>
</div>
<div class="three columns">
<button class="button" ng-click="delete()">x</button>
</div>
</div>
</li>
</ul>
Angular Code:
angular.module('todoTest', [])
.controller('todoController', function($scope) {
$scope.tasks = [];
$scope.add = function() {
$scope.tasks.push($scope.dotask);
}
$scope.update = function(){
$apply.tasks.push($scope.dotask);
}
$scope.delete = function() {
$scope.tasks.splice(this.$index, 1);
}
})
If you want to update the value you have to pass as parameter the position of the task inside the tasks array ($index is the position):
<button class="button" ng-click="update($index)">update</button>
And then the update function would be:
$scope.update = function(index){
$scope.tasks[index] = $scope.dotask;
}
Is that what you needed?
Button for updating. Visible only while updating.
<div class="row">
<button type="submit" class="u-full-width button button-primary">Criar Tarefa</button>
<button ng-show="updateMode" ng-click="update()" type="button" class="u-full-width button button-primary">Update</button>
</div>
New update function.
$scope.update = function(index) {
if ($scope.updateMode) {
$scope.tasks[$scope.updateIndex] = $scope.dotask;
$scope.updateMode = false;
} else {
$scope.dotask = $scope.tasks[index];
$scope.updateMode = true;
$scope.updateIndex = index;
}
If you click update on the task it will make the big update button visible and bring the old todo to the input. After hitting the big update button the todo task will update.
Plunker

Single function from multiple ng-show functions in a controller

I have a couple of functions that I've written in Angular to display multiple ng-show attributes on a page via scopes. I attempted to put all three into a single function using if else statements, but I couldn't get the function to fire for a second time. I'm wondering if there's a way to do this in a single function, and what the best practice for this sort of functionality is.
JS Fiddle is here - http://jsfiddle.net/ezy_/01L050mr/2/
Here's the JS that's currently spread across 3 different functions.
var app = angular.module('app',[]);
function AppCtrl($scope) {
$scope.skillsState = false;
$scope.rolesState = false;
$scope.qualsState = false;
$scope.skillsStateTrigger = function() {
$scope.skillsState = true;
$scope.rolesState = false;
$scope.qualsState = false;
};
$scope.rolesStateTrigger = function() {
$scope.skillsState = false;
$scope.rolesState = true;
$scope.qualsState = false;
};
$scope.qualsStateTrigger = function() {
$scope.skillsState = false;
$scope.rolesState = false;
$scope.qualsState = true;
};
}
Do I need a $watch or $apply function to trigger updates if I set the function to fire from a single statesTrigger(resp) function?
Have a look here: updated with 1 function
$scope.triggerState = function (state) {
if (state == 'skills') {
$scope.skillsStateTrigger();
} else if (state == 'roles') {
$scope.rolesStateTrigger();
} else if (state == 'quals') {
$scope.qualsStateTrigger();
}
}
<button ng-click="triggerState('skills')">Skills</button>
<button ng-click="triggerState('roles')">Roles</button>
<button ng-click="triggerState('quals')">Quals</button>
You can even be more specific in the HTML itself like this: State variable
<body ng-app="app" class="ng-scope">
<div class="container ng-scope" ng-controller="AppCtrl">
<button ng-click="currentState = 'skills'">Skills</button>
<button ng-click="currentState = 'roles'">Roles</button>
<button ng-click="currentState = 'quals'">Quals</button>
<div class="row" ng-show="currentState == 'skills'" style="display: none;">
Skills State Active
</div>
<div class="row" ng-show="currentState == 'roles'" style="display: none;">
Roles State Active
</div>
<div class="row" ng-show="currentState == 'quals'" style="display: none;">
Quals State Active
</div>
</div>
</body>
Here is your refactor. The trick is to use an object to store the 3 states.
js:
var app = angular.module('app',[]);
function AppCtrl($scope) {
$scope.states = {
skills: false,
roles: false,
quals: false
};
$scope.trigger_state = function(state) {
for(var i in $scope.states) {
$scope.states[i] = (i == state);
}
};
}
html:
<body ng-app="app" class="ng-scope">
<div class="container ng-scope" ng-controller="AppCtrl">
<button ng-click="trigger_state('skills')">Skills</button>
<button ng-click="trigger_state('roles')">Roles</button>
<button ng-click="trigger_state('quals')">Quals</button>
<div class="row" ng-show="states.skills" style="display: none;">
Skills State Active
</div>
<div class="row" ng-show="states.roles" style="display: none;">
Roles State Active
</div>
<div class="row" ng-show="states.quals" style="display: none;">
Quals State Active
</div>
</div>
</body>
In that case it's kinda a bad idea to use 3 states, you could use 1 one variable to store "state" = "mystate" for example (since the states are exclusive).

orderBy is not updating when I click on a button

Hope somebody can help me with my problem.
I am trying to order my list on specific data and this works fine when I say upfront on what it needs to be sorted.
But when I do this when I click on a button it doesn't order my list in anyway.
Hope somebody can help me with this problem.
this is my app.js code:
app.controller("ListController", function ($scope, $interval, $http, myService, OpenDataService) {
myService.async().then(function (d) {
OpenDataService.opendata = d;
$scope.openData = OpenDataService.opendata;
$scope.order = "";
});
$scope.orderOptions = ["gemeente", "locatie"];
$scope.change = function (value) {
console.log("change");
$scope.order = value;
console.log(value);
}
$scope.test = OpenWifiData;
});
And here is the html code I use:
<li ng-click="change('gemeente')"><a>locatie</a></li>
<div id="WifiSpots" ng-controller="ListController" class="col-sm-12 col-md-4 col-md-offset-2">
<div ng-repeat="item in openData | filter:searchText | orderBy: order">
<ul class="list-group">
<li class="list-group-item">
<div class="row wifiSpots" >
<div class="col-md-2">{{item.locatie}}</div>
<div class="col-md-2">{{item.gemeente}}</div>
<div clas="col-md-1">{{item.distance}}</div>
<div clas="col-md-1">{{item.duration}}</div>
<button ng-controller="MapController" ng-click="calculateAndDisplayRoute(item.objectid)" class="btn ">Selecteer</button>
</div>
</li>
</ul>
</div>
</div>
The 'order' in the ng-repeat directive is in a different scope than the one in your controller. Add a wrapper class like so:
$scope.opts = {order: ""};
Then in your change function update that instead:
$scope.opts.order = value;
In the html:
orderBy:opts.order

AngularJS not filtering products list

I am having an issue with AngularJS filtering my products list. I have done a few console.log queries on my variables and all seem fine. The problem is that the view does not update to show the filtered products.
Filtering works perfectly fine when you enter the search text in the input box but it does not work when clicking on the Category menu items.
I would like to filter the product list by category when the user clicks on the menu item.
Please see my code below and any help or advice is greatly appreciated.
My app.js
myApp.controller('StoreController', function($scope, $filter, storeFactory, cartFactory) {
$scope.cartTotal = 0;
$scope.cartItems = [];
$scope.categories = [];
$scope.counted = 0;
$scope.filteredProducts = {};
//get the products
storeFactory.getProducts(function(results) {
$scope.products = results.products;
$scope.counted = $scope.products.length;
$scope.filteredProducts = results.products;
});
$scope.$watch("search", function(query){
if($scope.filteredProducts.length) {
$scope.filteredProducts = $filter("filter")($scope.products, query);
$scope.counted = $scope.filteredProducts.length;
}
});
$scope.filterProductsByCategory = function(categoryName){
console.log('category filter');
/*$scope.products.forEach(function(o,i){
console.log('filter');
if( o.category_id !== categoryId ){
$scope.filteredProducts.splice(i,1);
console.log('removing');
console.log(o);
}
});*/
$scope.filteredProducts = $filter("filter")($scope.filteredProducts, categoryName);
console.info('the filtered items');
console.log($scope.filteredProducts);
$scope.counted = $scope.filteredProducts.length;
}
$scope.getCategories = function(){
storeFactory.getCategories(function(results){
$scope.categories = results.rows;
});
}
$scope.getCategories();
});
My store.htm
UPDATE :
I removed the extra controller reference and wrapped everything in one div.
<div ng-controller="StoreController">
<!-- the sidebar product menu -->
<div class="block-content collapse in">
<div class="daily" ng-repeat="category in categories | orderBy:'name'">
<div class="accordion-group">
<div ng-click="filterProductsByCategory(category.category_name)" class="accordion-toggle collapsed">{{category.category_name}}</div>
</div>
</div>
</div>
</div>
<!-- Load store items start -->
<div class="label">Showing {{counted}} Product(s)</div>
<div class="row" ng-repeat="product in filteredProducts | orderBy:'product_name'" style="margin-left: 0px; width: 550px;">
<hr></hr>
<div class="span1" style="width: 120px;">
<!-- <a data-toggle="lightbox" href="#carouselLightBox"> -->
<a data-toggle="lightbox" href="#carouselLightBox{{product.product_id}}">
<!--img alt={{ product.product_name }} ng-src="{{product.image}}" src="{{product.image}}" /-->
<img id="tmp" class="" src="images/products/{{product.product_image_filename}}" alt=""></img>
</a>
<div class="lightbox hide fade" id="carouselLightBox{{product.product_id}}" style="display: none;">
<div class='lightbox-content'>
<img src="images/products/{{product.product_image_filename}}" alt="" />
<!--img alt={{ product.product_name }} ng-src="{{product.image}}" src="{{product.image}}" /-->
<button class="btn btn-primary" id="close_lightbox" ng-click="closeBox(product.product_id, $event)">Close</button>
</div>
<style>
#close_lightbox
{
position: absolute;
top: 5px;
right: 5px;
}
</style>
</div>
</div>
<div class="span6" style="width: 330px; margin-bottom: 15px;">
<h5 style="font-size: 14px; font-weight: bold;">{{product.product_name}}</h5>
<p>{{product.product_description }}</p>
<p>Category : {{product.category_name}}</p>
</div>
<div class="span3">
<p class="price">Price : <strong>R{{ product.product_price }}</strong></p>
</div>
</div>
<!-- end of controller -->
</div>
$scope.filteredProducts = {};
//get the products
storeFactory.getProducts(function (results) {
$scope.products = results.products;
$scope.counted = $scope.products.length;
$scope.filteredProducts = results.products;
});
Is results.products an array of objects or an object of objects? Because $filter('filter')($scope.products,query); expects $scope.products to be an array.
$scope.$watch("search", function (query) {
if($scope.filteredProducts.length) {
$scope.filteredProducts = $filter("filter")($scope.products, query);
$scope.counted = $scope.filteredProducts.length;
}
});
Here's what I'm thinking this should look like and you won't need the $watch statement or the filteredProducts array/object, In controller:
$scope.search = '';
$scope.products = [];
$scope.categories = ['category1','category2','category3'];
// assuming that your store function getProducts returns a promise here
storeFactory.getProducts().then(function(results){
$scope.products = results.products; // needs to be an array of product objects
});
$scope.filterProductsByCategory = function(category){
$scope.search = category;
};
Then in your HTML Partial, this is not exactly how your's is, I'm just showing you here in shorter form what is possible:
<button ng-repeat="cat in categories" ng-click="filterProductsByCategory(cat)">{{cat}}</button>
<div class="row" ng-repeat="product in products | filter:search | orderBy:'product_name'">
<!-- Product Information Here -->
</div>
I created a JSFiddle to demonstrate: http://jsfiddle.net/mikeeconroy/QL28C/1/
You can free form search with any term or click a button for a category.
The side bar is using one instance of StoreController, and the main div is using another instance of StoreController. Each instance having its own scope. The should both use the same controller instance: wrap everything inside a div, and use a unique StoreController for this wrapping div.

Categories