I'm asking if is possible to do something as that in angular
<div ng-app="app">
<div ng-controller="mainController">
<ul ng-repeat="movie in movies |searchFilter:Filter.genre | searchFilter:Filter.name |searchFilter:Filter.pic ">
<li>{{movie.name}}</li>
</ul>
<h2>genre</h2>
<div>
<label>Comedy </label><input type="checkbox" ng-model="Filter.genre.Comedy" ng-true-value="Comedy" data-ng-false-value=''/><br/>
</div>
<h2>PIC</h2>
<label>aa</label><input type="checkbox" ng-model="Filter.pic.aa" ng-true-value="ciao" data-ng-false-value=''/><br/>
<h2>Name</h2>
<label>Shrek</label><input type="checkbox" ng-model="Filter.name.Shrek" ng-true-value="The God" data-ng-false-value=''/><br/>
</div>
</div>
i'm creating a checkbox for filter on different fields (size,name,genre)
ill have a list of avaible sizes,names and genres .
The issue is on ng-model and i tried to write it as "Filter.genre.genre.name" or
"Filter["genre"+genre.name]" and also "Filter.genre[genre.name]" but still not work .
the js.file is
var app =angular.module('app', []);
app.controller('mainController', function($scope) {
$scope.movies = [{name:'Shrek', genre:'Comedy',pic:"cc"},
{name:'Die Hard', genre:'Comedy',pic:"aa"},
{name:'The Godfather', genre:'Drama',pic:"ciao"},
{name:'The Godher', genre:'Comedy',pic:"lel"}];
$scope.genres = [{name:"Comedy"},{name:"Action"},{name:"Drama"}];
});
app.filter('searchFilter',function($filter) {
return function(items,searchfilter) {
var isSearchFilterEmpty = true;
//searchfilter darf nicht leer sein
angular.forEach(searchfilter, function(searchstring) {
if(searchstring !=null && searchstring !=""){
isSearchFilterEmpty= false;
}
});
if(!isSearchFilterEmpty){
var result = [];
angular.forEach(items, function(item) {
var isFound = false;
angular.forEach(item, function(term,key) {
if(term != null && !isFound){
term = term.toLowerCase();
angular.forEach(searchfilter, function(searchstring) {
searchstring = searchstring.toLowerCase();
if(searchstring !="" && term.indexOf(searchstring) !=-1 && !isFound){
result.push(item);
isFound = true;
// console.log(key,term);
}
});
}
});
});
return result;
}else{
return items;
}
}
});
if i make 3 different labels for the field Comedy, Action and Drama with ng-models called as
ng-model="Filter.genre.Comedy" ; ng-model="Filter.genre.Action" and ng-model="Filter.genre.Drama"
it work but it doesnt work if i try to write it into ng-repeat . I hope to have been clearer
In this sample i try to handle your question by change the Model of your page.
we have:
list of movies array => $scope.movies = []
dynamic filters array => $scope.genres = [], $scope.years = [] or more
our target:
Create a dynamic filters to search in movies
what we do
$scope.filterHandler = function (key, value) {}
Run when user start searching on input or select, this function help us to create a filter as object by sending key and value which result is {key:value}
$scope.searchTypeHandler = function (type, dependTo) {}
Run when our filters has some array for example genre has genres as dropdown select, this function help us to return the array which depend to the filter.
var app = angular.module("app", []);
app.controller("ctrl", [
"$scope",
function($scope) {
//your options
$scope.movies = [{
name: 'Shrek',
genre: 'Comedy',
year: 2000
},
{
name: 'Die Hard',
genre: 'Action',
year: 2000
},
{
name: 'The Godfather',
genre: 'Drama',
year: 2015
},
{
name: 'The Godher',
genre: 'Comedy',
year: 2017
}
];
$scope.genres = [{
name: "Comedy"
},
{
name: "Action"
},
{
name: "Drama"
}
];
$scope.years = [{
name: 2000
},
{
name: 2015
},
{
name: 2017
}
];
//
$scope.filter = {}
$scope.filterHandler = function(key, value) {
var object = {};
object[key] = value;
$scope.filter["find"] = object;
};
$scope.searchTypeHandler = function(type, dependTo) {
$scope.filter = {};
$scope.filter.searchType = type;
$scope.filter.options = undefined;
if (dependTo != null) {
$scope.filter.options = $scope[dependTo];
}
};
//default
$scope.searchTypeHandler("name");
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<div class="container" ng-app="app" ng-controller="ctrl">
<div class="page-header">
<div class="row">
<div class="col-lg-12">
<div class="col-lg-6 col-md-6 col-sm-6 col-xs-6">
<h4>Movies</h4>
</div>
<div class="col-lg-6 col-md-6 col-sm-6 col-xs-6 pull-right">
<div class="input-group">
<div class="input-group-btn">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
By {{filter.searchType}}
<span class="caret"></span>
</button>
<ul class="dropdown-menu dropdown-menu-left">
<li><a ng-click="searchTypeHandler('genre', 'genres')">Filter By Genre</a></li>
<li><a ng-click="searchTypeHandler('name', null)">Filter By Name</a></li>
<li><a ng-click="searchTypeHandler('year', 'years')">Filter By Year</a></li>
</ul>
</div>
<input ng-hide="filter.options" type="text" class="form-control" ng-model="filter.query" ng-change="filterHandler(filter.searchType, filter.query)">
<select ng-show="filter.options" class="form-control" ng-model="filter.option" ng-change="filterHandler(filter.searchType, filter.option)" ng-options="option.name as option.name for option in filter.options"></select>
</div>
<!-- /input-group -->
</div>
</div>
</div>
</div>
<ul class="list-group">
<li class="list-group-item" ng-repeat="movie in movies | filter: filter.find">
{{movie.name}} - <label class="label label-info">Ggenre: {{movie.genre}}</label> - <label class="label label-default">Year: {{movie.year}}</label>
</li>
</ul>
</div>
Related
I am new to AngularJS. I am trying to work out an example of a SportsStore app from a book I am following.
In this app, there are several categories of products. Categories are also displayed on the left side of the view.
Clicking a "category" is going to filter the products by category and is going to highlight the Category button.
Reading tutorials on net I understand that the "controller as" syntax is being favored over the "$scope" syntax.
How do I pass a filter (categoryFilterFn) to my controller function for filtering the products by category?
app.html
<!DOCTYPE html>
<html ng-app="SportsStoreApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular-resource.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.css" rel="stylesheet" />
<script src='app.js'></script>
<script src='customFilters.js'></script>
<script src='productListControllers.js'></script>
</head>
<body ng-controller="SportsStoreCtrl as controller">
<div class="navbar navbar-inverse">
<a class="navbar-brand" href="#">SPORTS STORE</a>
</div>
<div class="panel panel-default row" ng-controller="ProductListCtrl">
<div class="col-xs-3">
<a ng-click="selectCategory()"
class="btn btn-block btn-default btn-lg">Home</a>
<a ng-repeat="item in controller.data.products | orderBy:'category' | unique_selection:'category'"
ng-click="selectCategory(item)" class=" btn btn-block btn-default btn-lg"
ng-class="getCategoryClass(item)">
{{item}}
</a>
</div>
<div class="col-xs-8">
<div class="well" ng-repeat="item in controller.data.products | filter:categoryFilterFn">
<h3>
<strong>{{item.name}}</strong>
<span class="pull-right label label-primary">
{{item.price | currency}}
</span>
</h3>
<span class="lead">{{item.description}}</span>
</div>
</div>
</div>
</body>
</html>
customFilters.js
angular.module("customFilters", [])
.filter("unique_selection", function(){
return function(data, propertyName) {
if (angular.isArray(data) && angular.isString(propertyName)) {
var results = [];
var keys = {};
for (var i = 0; i < data.length; i++) {
var val = data[i][propertyName];
if (angular.isUndefined(keys[val])) {
keys[val] = true;
results.push(val);
}
}
return results;
} else {
return data;
}
}
});
app.js
var app = angular.module("SportsStoreApp", ['customFilters']);
app.controller("SportsStoreCtrl", function(){
this.data = {
products: [
{ name: "Product #1", description: "A product",
category: "Category #1", price: 100 },
{ name: "Product #2", description: "A product",
category: "Category #1", price: 110 },
{ name: "Product #3", description: "A product",
category: "Category #2", price: 210 },
{ name: "Product #4", description: "A product",
category: "Category #3", price: 202 }
]
};
});
productListControllers.js
angular.module("SportsStoreApp")
.constant('productListActiveClass', "btn-primary")
.controller('ProductListCtrl', function($scope, $filter, productListActiveClass) {
var selectedCategory = null;
$scope.selectCategory = function(newCategory) {
selectedCategory = newCategory;
};
$scope.categoryFilterFn = function(product) {
return selectedCategory == null ||
product.category == selectedCategory;
};
$scope.getCategoryClass = function(category) {
return selectedCategory = category ? productListActiveClass : "";
};
});
In productListControllers.js, how do I not use "$scope" object and use "this" object along with "$filter" argument? Also, how can I use "ProductListCtrl as product_ctrl" in app.html?
If you want to use your custom filter inside a controller, simply inject your custom filter into your controller using the name of your filter and the suffix Filter.
In your instance you need to inject unique_selectionFilter. You can then use it in your controller passing in your data and property name values:
unique_selectionFilter(data, propertyName)
Alternatively you can inject the $filter service and access your filter through it by passing in it's name:
$filter('unique_selection')(data, propertyName)
I'm new to angular and having some trouble setting this up. How do you setup a form and controller to push a new object into an existing array?
index.html:
<html ng-app="gemApp">
<div ng-controller="storeController as store">
<h3>Gems</h3>
<div ng-repeat="item in store.products" | orderBy:"name">
<h5>{{item.name}}</h5>
<h5>{{item.price | currency}}</h5>
</div>
</div>
app.js:
var app = angular.module("gemApp", []);
app.controller("storeController", storeController)
function storeController(){
this.products = gems;
}
var gems = [
{ name: 'Azurite', price: 2.95 },
{ name: 'Bloodstone', price: 5.95 },
{ name: 'Zircon', price: 3.95 }
];
This is a very basic sample of how you could do it. Bear in mind that I omitted validations, etc. and that the data stored here is just kept in memory. For storing this in time you have to save it to a database.
Snippet
var app = angular.module("gemApp", []);
app.controller("storeController", storeController)
function storeController() {
var self = this;
self.products = gems;
self.current = {};
this.add = function() {
gems.unshift(angular.copy(self.current));
self.current = {};
}
}
var gems = [{
name: 'Azurite',
price: 2.95
},
{
name: 'Bloodstone',
price: 5.95
},
{
name: 'Zircon',
price: 3.95
}
];
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="gemApp" ng-controller="storeController as store">
<form>
<label>Name</label>
<input type="text" ng-model="store.current.name">
<br>
<label>Price</label>
<input type="number" ng-model="store.current.price">
<br>
<input type="button" value="Guardar" ng-click="store.add()">
</form>
<h3>Gems</h3>
<div ng-repeat="item in store.products" | orderBy: "name">
<h5>{{item.name}}</h5>
<h5>{{item.price | currency}}</h5>
</div>
</div>
I have problem, would you help me. I have 2 views below. In the first, i use table, $scope.products can update data when change value input product.pick_qty. But in the seconds view, i use list, $scope.products can not update.
The first view html
<div class="row" ng-repeat="product in products">
<div class="col col-40">
<span>{{`product.product_name`}}</span></br>
<span class="italic">Size: {{product.size}}, </span>
<span class="italic">Color: {{product.color}}</span>
</div>
<div class="col col-20">{{`product.barcode`}}</div>
<div class="col col-20">{{product.request_qty}}</div>
<div class="col col-20"><input type="text" class="col-50 pick_qty" ng-model="product.pick_qty" /></div>
</div>
The seconds view html
<div class="list animate-fade-slide-in-right" ng-repeat="product in products ">
<a class="item item-icon-right in">
<h2>{{product.product_name}}</h2>
<p>
<span class="italic">Size: {{product.size}}, </span>
<span class="italic">Color: {{product.color}}, </span>
<span class="italic">Request Qty: {{product.request_qty}}</span>
</p>
<label class="item-input item-floating-label">
<span class="input-label">Pick Qty</span>
<input type="text" placeholder="Pick Qty" ng-model="product.pick_qty" >
pick_qty: {{product.pick_qty}}
products :{{products}}
</label>
</a>
</div>
Here is the same my controller ($scope.products i get from server have same structure), i want to $scope.products update field pick_qty when i change value input.
$scope.products = [
{
barcode: null,
color: "Black",
product_id: "528",
product_name: "TriBeCa Skinny Jean",
request_qty: 10,
size: "27"
},
{
barcode: null,
color: "Black",
product_id: "370",
product_name: "Isla Crossbod",
request_qty: 10,
size: "27"
}
];
var addParamsConfirm = function(){
var paramsConfirm = {};
paramsConfirm.data = [];
angular.forEach($scope.products, function(product){
angular.forEach(listPicked, function(item){
if(product.product_id === item.product_id){
if( product.pick_qty <= ( product.request_qty - item.picked_qty )){
paramsConfirm.data.push({
product_id: product.product_id,
qty: product.pick_qty
});
paramsConfirm.action = action.pick;
paramsConfirm.shop_id = 'BBB';
}
}
else {
if( (product.pick_qty > 0) && (product.pick_qty <= product.request_qty)){
paramsConfirm.data.push({
product_id: product.product_id,
qty: product.pick_qty
});
paramsConfirm.action = action.pick;
paramsConfirm.shop_id = 'BBB';
}
}
})
});
return paramsConfirm;
}
I'm developoing a web app and stuck here:
Part of the HTML:
<div class="input-group">
<select name="select" class="form-control input-group-select" ng-options="key as key for (key , value) in pos" ng-model="word.pos" ng-change="addPos()">
<option value="">Choose a POS</option>
</select>
<span class="sort"><i class="fa fa-sort"></i></span>
</div>
<ul class="listGroup" ng-show="_pos.length > 0">
<li class="list" ng-repeat="item in _pos track by $index">
<span>
{{item.pos}}
<span class="btn btn-danger btn-xs" ng-click="delPos($index)">
<span class="fa fa-close"></span>
</span>
</span>
<!-- I wanna add the input which can add more list item to the item.pos-->
<div class="input-group">
<a class="input-group-addon add" ng-class=" word.newWordExp ? 'active' : ''" ng-click="addItemOne()"><span class="fa fa-plus"></span></a>
<input type="text" class="form-control exp" autocomplete="off" placeholder="Add explanation" ng-model="word.newWordExp" ng-enter="addExpToPos()">
{{word.newWordExp}}
</div>
</li>
</ul>
Part of the js:
$scope._pos = [];
$scope.addPos = function () {
console.log("You selected something!");
if ($scope.word.pos) {
$scope._pos.push({
pos : $scope.word.pos
});
}
console.dir($scope._pos);
//console.dir($scope.word.newWordExp[posItem]);
};
$scope.delPos = function ($index) {
console.log("You deleted a POS");
$scope._pos.splice($index, 1);
console.dir($scope._pos);
};
$scope.addItemOne = function (index) {
//$scope.itemOne = $scope.newWordExp;
if ($scope.word.newWordExp) {
console.log("TRUE");
$scope._newWordExp.push({
content: $scope.word.newWordExp
});
console.dir($scope._newWordExp);
$scope.word.newWordExp = '';
} else {
console.log("FALSE");
}
};
$scope.deleteItemOne = function ($index) {
$scope._newWordExp.splice($index, 1);
};
So, what am I wannt to do is select one option and append the value to $scope._pos, then display as a list with all of my selection.
And in every list item, add an input filed and add sub list to the $scope._pos value.
n.
explanation 1
explanation 2
explanation 3
adv.
explanation 1
explanation 2
So I don't know how to generate dynamic ng-model and use the value in javascript.
Normaly should like ng-model="word.newExplanation[item]" in HTML, but in javascript, $scope.word.newExplanation[item] said "item is not defined".
can any one help?
If I've understood it correclty you could do it like this:
Store your lists in an array of object this.lists.
The first object in the explanation array is initialized with empty strings so ng-repeat will render the first explanation form.
Then loop over it with ng-repeat. There you can also add dynamically the adding form for your explanation items.
You can also create append/delete/edit buttons inside the nested ng-repeat of your explanation array. Append & delete is already added in the demo.
Please find the demo below or in this jsfiddle.
angular.module('demoApp', [])
.controller('appController', AppController);
function AppController($filter) {
var vm = this,
explainTmpl = {
name: '',
text: ''
},
findInList = function (explain) {
return $filter('filter')(vm.lists, {
explanations: explain
})[0];
};
this.options = [{
name: 'option1',
value: 0
}, {
name: 'option2',
value: 1
}, {
name: 'option3',
value: 2
}];
this.lists = [];
this.selectedOption = this.options[0];
this.addList = function (name, option) {
var list = $filter('filter')(vm.lists, {
name: name
}); // is it in list?
console.log(name, option, list, list.length == 0);
//vm.lists
if (!list.length) {
vm.lists.push({
name: name,
option: option,
explanations: [angular.copy(explainTmpl)]
});
}
};
this.append = function (explain) {
console.log(explain, $filter('filter')(vm.lists, {
explanations: explain
}));
var currentList = findInList(explain);
currentList.explanations.push(angular.copy(explainTmpl));
}
this.delete = function (explain) {
console.log(explain);
var currentList = findInList(explain),
index = currentList.explanations.indexOf(explain);
if (index == 0 && currentList.explanations.length == 1) {
// show alert later, can't delete first element if size == 1
return;
}
currentList.explanations.splice(index, 1);
};
}
AppController.$inject = ['$filter'];
<link href="http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demoApp" ng-controller="appController as ctrl">
<select ng-model="ctrl.selectedOption" ng-options="option.name for option in ctrl.options"></select>
<input ng-model="ctrl.listName" placeholder="add list name" />
<button class="btn btn-default" title="add list" ng-click="ctrl.addList(ctrl.listName, ctrl.selectedOption)"><i class="fa fa-plus"></i>
</button>
<div class="list-group">Debug output - current lists:<pre>{{ctrl.lists|json:2}}</pre>
<div class="list-group-item" ng-repeat="list in ctrl.lists">
<h2>Explanations of list - {{list.name}}</h2>
<h3>Selected option is: {{ctrl.selectedOption}}</h3>
<div class="list-group" ng-repeat="explain in list.explanations">
<div class="list-group-item">
<p class="alert" ng-if="!explain.title">No explanation here yet.</p>
<div class="well" ng-if="explain.title || explain.text">
<h4>
{{explain.title}}
</h4>
<p>{{explain.text}}</p>
</div>Title:
<input ng-model="explain.title" placeholder="add title" />Text:
<input ng-model="explain.text" placeholder="enter text" />
<button class="btn btn-primary" ng-click="ctrl.append(explain)">Append</button>
<button class="btn btn-primary" ng-click="ctrl.delete(explain)">Delete</button>
</div>
</div>
</div>
</div>
</div>
How to make the button functional, and the button has default value, for example button A-B has a range for a to b of first letter to be filter. Thanks, Sorry for my last post, it was hard to understand. =)
var app = angular.module('app', []);
app.filter('startsWithLetter', function () {
return function (items, letter) {
var filtered = [];
var letterMatch = new RegExp(letter, 'i');
for (var i = 0; i < items.length; i++) {
var item = items[i];
if (letterMatch.test(item.name.substring(0, 1))) {
filtered.push(item);
}
}
return filtered;
};
});
app.controller('PersonCtrl', function () {
this.friends = [{
name: 'Andrew'
}, {
name: 'Baldo'
}, {
name: 'Carlo'
}, {
name: 'Delo'
}, {
name: 'Emman'
}, {
name: 'Ferman'
}];
});
</style>
<script src="//code.angularjs.org/1.3.0-beta.7/angular.js"></script>
<style>
<div ng-app="app">
<div ng-controller="PersonCtrl as person">
<input type="text" ng-model="letter" placeholder="Enter a letter to filter">
<button>A-B</button>
<button>C-D</button>
<button>E-F</button>
<ul>
<li ng-repeat="friend in person.friends | startsWithLetter:letter">
{{ friend }}
</li>
</ul>
</div>
</div>
Is this what you meant? Did you want clicking each button to filter by those 2 letters?
All I changed was set the markup for the buttons to be:
<button ng-click="letter='[AB]'">A-B</button>
<button ng-click="letter='[CD]'">C-D</button>
<button ng-click="letter='[EF]'">E-F</button>
var app = angular.module('app', []);
app.filter('startsWithLetter', function () {
return function (items, letter) {
var filtered = [];
var letterMatch = new RegExp(letter, 'i');
for (var i = 0; i < items.length; i++) {
var item = items[i];
if (letterMatch.test(item.name.substring(0, 1))) {
filtered.push(item);
}
}
return filtered;
};
});
app.controller('PersonCtrl', function () {
this.friends = [{
name: 'Andrew'
}, {
name: 'Baldo'
}, {
name: 'Carlo'
}, {
name: 'Delo'
}, {
name: 'Emman'
}, {
name: 'Ferman'
}];
});
</style>
<script src="//code.angularjs.org/1.3.0-beta.7/angular.js"></script>
<style>
<div ng-app="app">
<div ng-controller="PersonCtrl as person">
<input type="text" ng-model="letter" placeholder="Enter a letter to filter">
<button ng-click="letter='[AB]'">A-B</button>
<button ng-click="letter='[CD]'">C-D</button>
<button ng-click="letter='[EF]'">E-F</button>
<ul>
<li ng-repeat="friend in person.friends | startsWithLetter:letter">
{{ friend }}
</li>
</ul>
</div>
</div>