mdChips with filter - angularjs

I'm a Newbie to AngularJS trying something with Angular Material and need some ideas / help.
I have icons of Font Awesome which are displayed with ng-repeat:
<ul ng-repeat="item in items">
<i ng-class="{'test': item.active}" class="fa fa-{{item.name}}">{{item.name}}</i>
</ul>
Below I have a list of the icons a with checkboxes:
<span ng-repeat="item in items | filter: item.active = false">
<input type="checkbox" ng-model="item.active"> {{item.name}}<br>
</span>
If a checkbox is activated, the list entry should disappear from the list.
This works with the filter of the property item.active
Now I want to display the activated items above the list with md-chips (Angular Material Chips).
So if a list item is activated, the element should be a md chip above the list (not displayed in the list anymore).
If I click on the 'X' in md-chip, only the state of the property item.active should change again to false.
I have my working files on Plunker, so my current working state can be read:
https://plnkr.co/edit/t3Xpp2AKEJHXBWhkLUYZ?p=preview
Does anybody got an idea how can I implement this?

The easiest way to do that is apply ng-click to your md-chip item and by this click it will set active = false:
...
<md-chips class="custom-chips" ng-model="items | filter: {active:true}" readonly="true">
<md-chip-template>
<span ng-click="$chip.active=false">
<strong>{{$chip.name}}</strong>
</span>
</md-chip-template>
</md-chips>
...
Here is a plnkr example.
EDIT:
Modified plunker to show only active md-chips.
Hope it will help.

You may want to filter the chips array using the builtin filterFilter function. The watcher that contains the latter will invoke the listener whenever the filterText changes.
...
$scope.array = [
"active directory",
"outlook",
"edrm",
"gcdocs",
"novell",
"iPrint",
"iManager",
"sigma",
"bitlocker",
];
$scope.filterText = "";
$scope.$watch('filterText', function(newValue, oldValue) {
$scope.filteredArray = filterFilter($scope.array, $scope.filterText);
}, false);
...
The following markup will render and filter the chipset.
<md-content flex class="md-padding">
<label>Filter: <input ng-model="searchText"></label>
<md-chips ng-model="filteredArray" readonly="ctrl.readonly"
md-removable="removable" placeholder="Enter an issue...">
<md-chip-template>
<strong>{{$chip}}</strong>
</md-chip-template>
</md-chips>
</md-content>
For further information on filters please see https://docs.angularjs.org/guide/filter
For further information on $watch please see https://docs.angularjs.org/api/ng/type/$rootScope.Scope

Related

Angular Material's md-checkbox - all checkboxes check when using ng-model.

The radio choice, styled as a checkbox, works great like this with no issues:
<div ng-repeat="choice in regions| orderBy: 'description'">
<input type="radio"
value="{{choice.name}}"
name="regionRadio"
ng-model="radio.region">
{{choice.description}}
</div>
input[type="radio"] {
-webkit-appearance: checkbox;
-moz-appearance: checkbox;
-ms-appearance: checkbox;
}
However, if I want to use Angular Materials md-checkbox:
<div ng-repeat="choice in regions| orderBy: 'description'">
<md-checkbox type="radio"
value="{{choice.name}}"
ng-model="radio.region">
{{choice.description}}
</md-checkbox>
</div>
It does not handle the ng-model well. When just one checkbox is selected, all the checkboxes become selected(checked).
Any suggestions how to make md-checkbox work in the same manner with ng-model as before?
Your question is a bit confusing. md-checkbox does not have the attribute type according to the docs. You should really use md-radio-group to stay within AM best practice.
I have created an example with md-checkbox and md-radio-group - CodePen
Clicking a checkbox does not select all the checkboxes but you can select more than one checkbox. It's quite easy to write some code to make the checkboxes act like radio buttons though.
Markup
<div ng-controller="AppCtrl" ng-cloak="" ng-app="MyApp">
<p>Checkbox</p>
<div ng-repeat="choice in regions| orderBy: 'description'">
<md-checkbox type="radio"
value="{{choice.name}}"
ng-model="radio.region">
{{choice.description}}
</md-checkbox>
</div>
<p>{{radio.region}}</p>
<p>Radio Group</p>
<md-radio-group ng-model="newradio.region">
<md-radio-button ng-repeat="choice in regions| orderBy: 'description'" value="{{choice.name}}" class="md-primary">{{choice.description}}</md-radio-button>
</md-radio-group>
<p>{{newradio.region}}</p>
</div>
JS
angular.module('MyApp',['ngMaterial'])
.controller('AppCtrl', function($scope) {
$scope.regions = [
{name: "sky", description: "The sky"},
{name: "sea", description: "The sea"},
{name: "land", description: "The land"},
{name: "water", description: "The water"}
];
});
I'll take a shot in the dark and assume you had the same (or very similar) issue as me. I was stunned to search and find this issue was unique to you and me until I started to look into my parent containers and realized my mistake.
My issue was that I included my md-checkbox INSIDE an md-list-item. Upon clicking anywhere in that md-list-item, my md-checkbox toggled. In retrospect, I should have noticed sooner with the giveaway ripple effect.
The md-checkbox directive is one of the proxied elements that gets triggered when clicking inside an md-list-item. Adding the class "md-no-proxy" to the md-list-item element removes this (and the ripple) effect.*
If you were not using a parent md-list-item element, I suggest looking into whether or not any of your parent containers/directives proxies an ng-click in it's children elements.
*Source:
https://material.angularjs.org/latest/api/directive/mdListItem

Angular Select Tag with Bootstrap Dropdown Styling

I need to create custom styling for a select dropdown (including the options). The more I've dug into this, the more I've realized that styling options is quite difficult.
I'm currently using Bootstrap's dropdown and it works great, except for the fact that I have to use a function to assign a value.
This is how I am currently using a 'custom select dropdown':
<div class="form-element-container">
<div class="drop-down dropdown-toggle">
<label for="chooseAdvisor"></label>
<div>
<button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown">{{mySelection}}</button>
<ul class="dropdown-menu">
<li ng-repeat="option in options">{{option}}</li>
</ul>
</div>
</div>
</div>
You can see that on click, I have to manually set the option in my controller rather than it being directly bound to my model. Is there any way that I can use Bootstrap's dropdown styling with angular's select tag?
I would love to be able to use my options repeater with 'track by', etc:
<select ng-options="item as item.label for item in items track by item.id" ng-model="selected"></select>
You can try it:
https://angular-ui.github.io/bootstrap/#/dropdown
Just a suggestion, I've not tested it yet.
Update answer:
I think you can instead of angular module : acute-select
https://github.com/john-oc/acute-select
Demo : http://john-oc.github.io/

AngularJS Show List Items based on ng-model

I'm trying to create some functionality where the user would have an input box and all the data (li's) below are hidden.
Then when a user types into the input box, those li's that match that text are show.
What would the best way to do this using angular? I've set up plunker below:
http://plnkr.co/edit/T6JOBJE4LrAtshbmaoPk?p=preview
I was thinking of setting the li's to:
li {
display: none;
}
and then was going to try an ng-if with the ng-model as the value. Something like this:
<div class="input-group">
<span class="input-group-addon" id="basic-addon1">Search</span>
<input type="text" class="form-control" ng-model="search">
</div>
<ul>
<li ng-repeat="x in data | filter:search " ng-if="!search">{{x.name}}</li>
</ul>
Can someone help point me in the right direction? Even if its just explaining the logic.
You can just set ng-show attribute to your <ul> tag, where you will watch on length of search variable and if it's greater that zero, your list with filtered results will be shown. So, you don't need any css.
<ul ng-show="search.length">
<li ng-repeat="x in data | filter:search ">{{x.name}}</li>
</ul>
Demo on plunker.
Part of your problem is the filter matches on the empty search string. You could create a custom filter to handle this, something like this http://plnkr.co/edit/i4lsuVUmOLO3pbISu7FR?p=preview
$scope.filterName = function(datum) {
console.log($scope.search, datum);
return $scope.search !== '' && datum.name.indexOf($scope.search) !== -1;
};
Used in the template like:
<ul>
<li ng-repeat="x in data | filter:filterName">{{x.name}}</li>
</ul>
Then you would have greater control over the filter if you want to tweak it in future.

Adding a ng-click attribute to the header value of an accordion group

I am trying to track the order in which a user clicks the headers of a bootstrap accordion. I am running into trouble trying to add a ng-click attribute to the repeated accordion-group. I am trying to limit the click area to just the header text, not the entire group. I thought a good way to do this was to pass the click $event into the ng-click function, but it is not working.
Here is a Plunker with the broken ng-click attribute here:
http://plnkr.co/edit/yOTRVRjxRDTlnZ9Qwsk4?p=preview
Can someone kindly help me figure out the best Angular way to solve this?
You can use the accordion-heading for the custom header.
Here is the sample:
<accordion-group close-others={{oneAtATime}} ng-repeat="(key, value) in groupedByCategory" is-open="value.open" >
<accordion-heading>
<a ng-click="clickTrack($event)">{{key}}</a>
</accordion-heading>
<div ng-repeat="c in value | orderBy: 'rating'">
<input type="radio" name="Category" value="{{c.name}}-{{key}} "> {{c.name}} | {{c.rating}}
</div>
</accordion-group>

ng-repeat Circular Reference Screen Refresh

I'm a noob to AngularJS. As a learning exercise I am creating a typeahead control.
The typeahead is comprised of a text box for filtering the options, an unordered list for displaying the menu of short-listed options, and a Show/Hide button for manually toggling the list.
The text box filters the li elements using ng-repeat. When selecting an li item from the list, I populate the text box with the selected value, and then hide the list.
<div class="xtab-typeahead" ng-controller="xTabTypeAheadCtrl">
<input type="text" class="xtab-typeahead-search" placeholder="{{type}}" ng-model="query.id" ng-focus="showMenu()" ng-init="query.id = undefined" />
<button ng-click="toggleMenu()">Show/Hide</button>
<ul class="xtab-typeahead-menu" ng-class="{true:'active',false:''}[isActive]">
<li ng-repeat="item in menuItems | filter:query"
ng-click="hideMenu(); query.id = item.id">
{{item.id}}
</li>
</ul>
</div>
My issue is that when the value is assigned to the text box, the list is momentarily filtered to the one option selected (because the text box is also the source of the ng-repeat filter), before hiding the menu. What I want id for the menu to be hidden without being refreshed with the filter first.
It should be noted that this only occurs when using CSS transitions which I am using to fade the menu out.
Here is a plnkr to illustrate.
Here's a working Plnkr. I basically gave your menu time to finish its animation before setting the value. Relevant code is as follows:
$scope.selectItem = function(id){
$scope.isActive = false;
$timeout(function(){
$scope.query.id = id;
}, 250);
}
...and the HTML using the newly created selectItem method:
<div class="xtab-typeahead" ng-controller="xTabTypeAheadCtrl">
<input type="text" class="xtab-typeahead-search" placeholder="{{type}}" ng-model="query.id" ng-focus="showMenu()" ng-init="query.id = undefined" />
<button ng-click="toggleMenu()">Show/Hide</button>
<ul class="xtab-typeahead-menu" ng-class="{true:'active',false:''}[isActive]">
<li ng-repeat="item in menuItems | filter:query"
ng-click="selectItem(item.id)">
{{item.id}}
</li>
</ul>
</div>

Resources