In the AngularJS phonecat tutorial, there is an input box which is used to apply a filter to ng-repeat. This works great for returning a subset array to display on the screen.
Here is what the code looks like:
Search: <input ng-model="query">
<ul class="phones">
...
<li ng-repeat="phone in phones | filter:query | orderBy:orderProp" class="thumbnail">
<img ng-src="{{phone.imageUrl}}">
{{phone.name}}
<p>{{phone.snippet}}</p>
</li>
</ul>
I was wondering what's the best way to dynamically add a CSS class to matching elements. An example use case of this would be to add a background-color (style .matching{}) to all matching elements.
Comparing the query text in ng-class did NOT work:
<li ng-repeat="phone in phones" class="thumbnail">
<img ng-src="{{phone.imageUrl}}">
{{phone.name}}
<p>{{phone.snippet}}</p>
</li>
</ul>
I am new to angular and trying to just get a feel for the framework. Do I have to bind the query text to the element somehow so that the comparison works? Would a better approach be to handle this through a custom directive?
Any help is appreciated - thanks!
Try setting the class to a function in the controller. ng-class="GetMatchingClass(phone)"
$scope.GetMatchingClass= function(phone){
if(phone.name.indexOf(query) != -1 ){return "matching"}
return "";
}
{{phone.name}}
that should do it for exact matches.
Related
I'm learning Angular 12 and I have some issues about the framework operation.
I've created a new project, added Bootstrap 5 and created some components.
When I nest a component inside another like this :
<div class="container">
<div class="row">
<div class="col-xs-12">
<h2>Mes appareils</h2>
<ul class="list-group">
<app-appareil [appareilName]="appareilOne"></app-appareil>
<app-appareil [appareilName]="appareilTwo"></app-appareil>
<app-appareil [appareilName]="appareilThree"></app-appareil>
</ul>
</div>
</div>
</div>
I don't understand why I still see the custom selectors in the browser inspector view :
Angular browser view
It breaks several things in my Boostrap style.
Did you know if it's possible to hide/remove these custom components of my browser view to get in this case only the <li> tags directly inside the <ul> instead of these <app-appareil> ?
Thanks :)
Change
#Component({
selector: "app-appareil"
})
to
#Component({
selector: "li[appAppareil]"
})
and then use it as
<ul class="list-group">
<li appAppareil [appareilName]="appareilOne"></li>
</ul>
By using an attribute selector we can avoid the wrapping component tag (which you cannot "remove"), and we preserve semantics of the DOM itself.
Likely to get better semantics you'd want to make further changes and use content projection, but that's unclear from the limited information and beyond the scope of the question anyway.
To make it the "Angular way", the approach needs to be changed.
Supposing that you have a collection of device names (appareilNames) returned from your component:
public get deviceNames(): Array<string> { ... }
The appropriate tags structure can be achieved as follows:
<ul class="list-group">
<li *ngFor="let deviceName of deviceNames"> <!-- iterate on each device name -->
<app-appareil [appareilName]="deviceName"></app-appareil> <!-- use each name to create a component with it -->
</li>
</ul>
Is it possible to dynamically add an ng-repeat attribute to an element?
If so, how?
EDIT:
I was trying to create a component that will use a custom template inside it for each items on its list.
Example
<custom-component>
<item-template>
<span>{{item.name}}</span>
<item-template>
<custom-component>
Then the result shall be
<custom-component>
<ul>
<li ng-repeat="item in $ctrl.items">(the template)</li>
</ul>
</custom-component>
So I tried to just set the innerHTML of the ul to a string like so:
ul.innerHtml = "<li ng-repeat="item in $ctrl.items">{{item.name}}</li>"
A solution would be showing an element which have ng-repeat depending on a condition that you can change dynamically:
<div ng-switch="dynamicCondition">
<div ng-switch-when="true" ng-repeat="item in items">Element which have ng-repeat</div>
<div ng-switch-when="false">Element without ng-repeat</div>
</div>
Hi I have two different list which I want to display. I was wondering how to use ng-repeat twice to get them printed.
This is the HTML page:
<div>
<div>Search: <input ng-model="query" placeholder="filter"></div>
<ul>
<li ng-repeat="doc in documents | filter:query | state in statusofdoc" ng-click="selectedDocument(doc)" >{{doc}}{{state}}</li>
</ul>
</div>
This thing just display the doc but does not display the state. How to get ng-repeat run for both?
I have just started ng and I must say it is too much fun! I am using example from this site
http://www.revillweb.com/tutorials/angularjs-in-30-minutes-angularjs-tutorial/ specifically the 'filter data with angular js'
I followed the example and works fine. The example shows the list and as you type the name it will filter it and show the exact match.
I didn't want to stop there and play with it more, what I want to do is not to show any list initially and as the user types the list is shown. Here is my index.html:
<div id='content' ng-app='MyTutorialApp' ng-controller='MainController'>
<input type='text' ng-init='searchText=" "' ng-model='searchText' />
<ul>
<li ng-repeat='person in people | filter:searchText'>#{{person.id}} {{person.name}}</li>
</ul>
</div>
as you can see I am doing ng-init on the searchText variable and this works fine when I initially open the page i.e. there is no list. But as I type a name the list stays there after filtering is done even when I clear the input box. How can I make the list disappear when I clear the input box?
Do I need some sort of custom filter?
please excuse my ignorance with ng if I am using incorrect terms and please tell me the correct ones :)
you can use ng-show/ng-hide to show/hide the list based on certain condition, as currently you want it on searchText
<ul ng-show="searchText !==''">
<li ng-repeat='person in people | filter:searchText'>#{{person.id}} {{person.name}}</li>
</ul>
Just an another idea to achive what you want:
<input type="text" ng-model="searchText" />
<ul>
<li ng-repeat="person in people | filter:(searchText || ' ')">#{{person.id}} {{person.name}}</li>
</ul>
or if you would like to filter by some default value when the input box is empty:
<li ng-repeat="person in people | filter:(searchText || 'John')">#{{person.id}} {{person.name}}</li>
I'm totally new to AngularJS, so would like some advice on how to do this.
Instead of creating several chunky 'blocks' of filter code, is it possible to neatly have several show/hide filters within a repeater? This would greatly ease the readability at first glance and is less code comparing to the Custom Filters/Tutorial 9 in the AngularJS site.
Something like:
<li ng-repeat="phone in phones | filter:(showIf phone.brand == 'Nexus') | orderBy:orderProp">
{{phone.name}}
<ul>
<li ng-repeat="price in phone.prices | filter:(showIf price < 100)">${{price}}</li>
</ul>
</li>
Edited:
Would this work and how do I hide the parent UL if there are no LIs?
<li ng-repeat="phone in phones | filter:{brand: 'Nexus'} | orderBy:orderProp">
{{phone.name}}
<ul>
<li ng-repeat="price in phone.prices | filter:{price: < 100}">${{price}}</li>
</ul>
</li>
Refer to the Filter dev guide in the Angular docs. It's entirely possible.
Your first example, showIf phone.brand == 'Nexus' is best done with the built-in Filter somewhat confusingly named filter.
<li ng-repeat="phone in phones | filter:{brand: 'Nexus'}">{{ phone }}</li>
Your second example is somewhat more complicated because of the < operator, but can be solved by using the same filter-filter with a custom comparator function, or by creating your own custom filter.
Example comparator function:
$scope.lessThan = function(expected, actual) {
return actual < expected;
}
Used like:
<li ng-repeat="price in phone.prices | filter:{price: 100}:lessThan">{{price}}</li>