Search in data showed in rows with 2 columns using ng-repeat - javascript

I showed a JSON data using ng-repeat in rows with 2 columns. I also have a search box to filter desired data. my code is as below:
<input type="text" ng-model="search" />
<div class="row" ng-repeat="x in books | filter:search" ng-if="$index%2==0">
<div class="col" >
{{x.name}} , {{x.type}}
</div>
<div class="col" >
{{books [$index+1].name}} , {{books [$index+1].type}} ` `
</div>
</div>
but when I use the search box, the results wont show correctly.
Sometimes it shows both desired data and its next index , sometimes it shows the desired data in both columns of a row and sometimes it shows nothing at all.
How should I make it correct ?
Thanks in advance.

$index refers to the index in the filter results, but you're using it to access the original array in the second inner div. So if you have books A B C in your list, and if you search for A, then the filter results will have one item but the original books array still has all three, and B will still appear because books[1] is B.
Instead of using rows and cols, could you place the ng-repeat on the inner div and wrap them inside a single container that gives you the width you want? If the inner divs use float: left or display: inline-block, you'd get a two-column list if the container is the right width.
<div class="books-container">
<div class="book" ng-repeat="x in books | filter:search">
{{x.name}} , {{x.type}}
</div>
</div>
Working example: https://plnkr.co/edit/MG4do0kqV8wk0nk9tlKJ?p=preview

Related

Angular 2+ switching betweens elements, based on click

So, I'm trying to use a angular way to send the buttons created to either the #start or #finish divs, based on click on the buttons selected, so in a way they would send themselves if you may if they follow a condition, which in this case is to be either inside of the #start or #finish divs. With Jquery, I just check what's the parent of certain element, if matches one, I send it to the other, and vice versa. Now with angular, I have been looking into the whole, rendering and stuff, but my head can't just understand the overall picture, and I even though I was able to click and send the element clicked to a different div, I couldn't do it with the other buttons created, and also with the button that was first clicked, in the other div.
<div class="ui raised very padded text container segment"
#finish>
</div>
<div class="ui raised very padded text container segment" #start>
<button
*ngFor='let word of ge_array'
(click)="goToNext()"
>{{word}}</button>
</div>
Does anybody know how to tackle this situation?
Renan, I would change all your plan. I have an array of element. this elements have a property "place". I will show in two div one for "plan1" and the other for "plan2".
//the .ts is like
items:any[]=[{word:'uno',place:1},{word:'dos',place:1},{word:'tres',place:2}]
get items1(){
return this.items.filter(it=>it.place==1);
}
get items2(){
return this.items.filter(it=>it.place==2);
}
//the .hmtl like
<h2>place 1</h2>
<button *ngFor="let item of items1" (click)="item.place=2">{{item.word}}</button>
<h2>place 2</h2>
<button *ngFor="let item of items2" (click)="item.place=1">{{item.word}}</button>
I would prefer using a getter and have "item1" and "item2". the click make that the property "place" of the item becomes 2 in place 1 and becomes 1 in place2
You can make two *ngFor over the same array also using a *ngIf like
<h1>place 1</h1>
<div *ngFor="let item of items">
<button *ngIf="item.place==1" (click)="item.place=2">{{item.word}}</button>
</div>
<h1>place 2</h1>
<div *ngFor="let item of items">
<button *ngIf="item.place==2" (click)="item.place=1">{{item.word}}</button>
</div>
and forget the getters

AngularJS ng-repeat, tables information dependencies

I created two tables in server side. The first one contains informations like house, room house, number, street ...
The second one contains informations like first_color, room house, second_color ...
Of course both tables have different number of columns and rows. For instance the first one has 5 rows and the second one only 2 rows (rows increase dynamically).
As you read before they both have one common information the "room house" data.
I need to change colors information of the first table with information of the second one depending on that link field 'room house'.
Here bellow is my HTML code using two times "ng-repeat" :
<div class="col-sm-6 col-md-4" ng-repeat="item in data.house | orderBy: '-count' | limitTo: data.limit">
<div ng-repeat="d in data.colors" ng-show="d.room_house == item.room_house">
<span style="color:{{::d.firsrt_color}}">{{::item.name}}</span>
</div>
<div>
<span style="color:#444444">{{::item.name}}</span>
</div>
</div>
However if the common information can't be find it doesn't display the rest of the table. I need to display the whole information within the first table with the color information inside the second one. If information can't be found (due to different numbers of rows between the two arrays or because data doesn't exist in the second one) I must continue to display information of the first array however with a default color.
Of course adding an html div with ng-show="d.room_house != item.room_house" doesn't work because it will display some information in two colors.
Controller 1
Controller 2
Hope someone will be able to help me.
Thank you
Instead of nested loops in HTML, you can move the logic to your controller and your HTML looks smaller and cleaner and the original issue will also be fixed.
Try this solution,
var defaultColor = "#444444";
data.house.forEach(function(house) {
house.color = defaultColor; // assign default color initially
var obj = data.colors.filter(function(x){
return x.room_house == house.room_house;
}
if(obj.length > 0) {
house.color = obj[0].firsrt_color;
}
});
<div class="col-sm-6 col-md-4" ng-repeat="item in data.house | orderBy: '-count' | limitTo: data.limit">
<div>
<span ng-style="{ color: item.color}">{{::item.name}}</span>
</div>
</div>
P.S: You've used "firsrt_color" instead of "first_color", I hope that's intended..

How to access previous ng-repeat element in an ordered array

I am trying to compare the previous element in a ng-repeat that is ordered to the current one. If the two appointments have the same DateString I don't want it to print out. You can see I try to prevent that in the ng-if.
<div ng-repeat="appointment in appointments | orderBy: 'milliSeconds' " ng-if="!noAppointments">
<div class="row row-date" ng-if="appointments[$index - 1].DateString != appointment.DateString">
<div class="col">
{{appointment.DateString}}
</div>
</div>
</div>
This does not work though. Do you guys have any suggestions on how this could be done?
I sorted the array in the controller and moved the logic there too to solve this.

How do I use nested ng-repeat in Angular Js?

I'm trying to repeat 4 elements in a 2x2 matrix format with top and bottom separate rows. For that I'm using ng-repeat to repeat the top and bottom rows and then another ng-repeat inside to repeat the two elements. I have done it and got the required format. But my problem is that I need to provide different titles for these 4 elements(div). How can I give the titles in an array so that it will be repeated in both rows? Below is my code:
<div class="massage-type-section" ng-controller="massageController">
<div class="select-massage-type" ng-repeat="item in massage">
<div class="massage-choice" ng-repeat="type in massageType">
<div class="massage-choice-icon">
<img src="images/single-icon-deselect.png">
<img src="images/single-icon.png">
</div>
<p class="massage-title">{{type.title}}</p>
<p class="section-details">One massage practitioner comes to massage one person.</p>
<div class="type-selected"><img src="images/selected.png"></div>
</div>
</div>
</div>
function massageController($scope) {
$scope.massage = [{}, {}];
$scope.massageType = [
{ title: 'Single' },
{ title: 'Couple' }
];
};
If your primary requirement in the inner array is only to display the massage Type titles, your array looks good. Please mark as answer if this helps.
if your requirement is to give different titles in different levels use $index or $parent.$index in appropriate way.
To find the index of an item in the collection use $index property
To get the index of the parent element
Use $parent.$index or
Use ng-init="parentIndex = $index"

How can I have arbitrary content inside an ng-repeat with Angular?

I have an ordered list of items that I want to be displayed. Getting this done with Angular is trivial:
<p>Filter a game: <input type="text" ng-model="search.name" /></p>
<game-card ng-repeat="game in games | filter:search" game ="game" size="large"></game-card>
This outputs an ordered list of games that has been sorted from the database. However, I want to show a few snippets of arbitrary content inside this ng-repeat. This diagram below indicates what I'm after. The lefthand side shows how it should look in the unfiltered state, the righthand side if a search term as present.
As you can see, I want to highlight the first item with a "Next up" heading, and following that, an "After that" heading. When a search is present, I don't want these headings at all as they won't be relevant.
I'm completely new to Angular ("you lost me at service" new, by the way), but have come from a Knockout.js background. What is the "Angular way" of solving this?
Stack up ng-if's on the headings and compare with $index? Does $index even care about the filter being applied?
Kind of dirty solution: within the ng-repeated element, put something like
<div ng-if="$index === 0">
<h2>Next up</h2>
</div>
<div ng-if="$index === 1">
<h2>After that</h2>
</div>
<div>
<!-- Your content goes here, unconditionally -->
</div>
And the obvious problem with this is that two tests are performed for each "instantiation" of the content of the ng-repeated element, and they are useless except for the first and second.
Otherwise you could place your first two bits of contents with headers outside the ng-repeat and then start repeating from index 2, but I'm not sure that's possible with ng-repeat.
If it's not, then split your data into firstElement, secondElement and rest where rest is Array.prototype.slice.call(/* your initial list of elements */, 2).
The problem with this last solution is that it requires you to adapt your data to how you present it, which is undesirable for obvious reasons.
edit: OK here's something better, not tested:
<div ng-if="elements.length > 0">
<h2>Next up</h2>
<div><!-- First content goes here, it uses elements[0] --></div>
</div>
<div ng-if="elements.length > 1">
<h2>After that</h2>
<div><!-- Second content goes here, it uses elements[1] --></div>
</div>
<div ng-repeat="element in elements.slice(2)">
<!-- The rest goes here, unconditionally -->
</div>
Instead of doing your ng-repeat in the game-card tag, do it in a wrapping div and then use ng-repeat special variables:
<p>Filter a game: <input type="text" ng-model="search.name" /></p>
<div ng-repeat="game in games | filter:search">
<div ng-if="$first">NEXT UP</div>
<div ng-if="$index === 1">AFTER THAT</div>
<game-card game="game" size="large"></game-card>
</div>
My solution was to ng-show the titles only if the length of the results passed through the filter equaled the total number of games:
<h2 ng-show="games.indexOf(game) == 1 && search.length == games.length">More Games</h2>

Categories

Resources