AngularJS ng-repeat, tables information dependencies - javascript

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..

Related

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"

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

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

Javascript code for alphabetizing divs

I'm editing a web page that has a list of doctors names and images wrapped in a div. I'm adding more to that list and my client wants all of the names in alphabetical order now. As apposed to manually doing that (I know my client will also be adding more doctors in the future)I tried writing a script to do the work for me. I wrapped each doctor in a div called "alphabetize," and set a span id of "lastName" around each doctor's last name.
<div class="alphabetize large-6 columns sameheight-wrap">
<div class="large-4 medium-4 columns sameheight PadT20"> <img src="../imgs/dev/crna-staff/John-Doe.jpg" alt=" John Doe, CRNA" class="pictureBottomBorder"> </div>
<div class="large-8 medium-8 columns contenttable sameheight PadT20">
<div class="border vmid text-center bgdblue PadB"> <span class="white medium"><strong>John<span id="lastName">Doe</span></strong><br>
</span> <span class="white PadT5"> MSN, Thomas Jefferson University School of Nurse Anesthesia</span> </div>
</div>
</div>
I placed the following script on that page;
<script>
var $divs = $("div.alphabetize");
$(function() {
var alphabeticallyOrderedDivs = $divs.sort(function (a, b) {
return $(a).find("#lastName").text() > $(b).find("#lastName").text();
});
$("#alpha").html(alphabeticallyOrderedDivs);
});
</script>
For some reason, the script is not working correctly. Doctors are out of order and i also need to add a variable to the code that sorts the last names with the first 3 letters. Can anyone help? Javascript is not my strong suit. Not sure if I missed something.
Below is a snippet that will show you how you can easily sort this. The major issue, however, is the following:
return $(a).find("#lastName").text() > $(b).find("#lastName").text();
The sort() function asks to return one of three values, 0 to maintain position, -1 to move it before the current element and 1 to move it after. That means that all you could ever return is after and not before, so your sort fails.
For the solution I would like to suggest using a data-attribute and no more HTML spans and styles that need to be rendered (and probably hidden afterwards), so here is my suggestion:
<div data-alphabetize="John Doe">John Does Content</div>
We can string together a couple of functions to get the correct output. We will need prototype.slice.call to convert the returned-by-querySelector NodeList to an Array, then we need to use sort to sort it alphabetically and finally we can use forEach to go through the array and insert the nodes in the correct position.
I am using vanilla JS - mostly to show how simple things can be done without loading up jQuery. You can, of course, do this with jQuery as well.
// Turn querySelectorAll NodeList into an Array
Array.prototype.slice.call(document.querySelectorAll('[data-alphabetize]'))
// Sort the array by data-alphabetize attribute (reverse order)
.sort(function(a, b){
return a.getAttribute('data-alphabetize') < b.getAttribute('data-alphabetize')
? 1 : -1;
})
// Insert every node in order
.forEach(function(v, i, a){
var parent = v.parentNode;
parent.removeChild(v);
parent.insertBefore(v, parent.childNodes[0]);
});
<div>
<div data-alphabetize="Beta">Joseph Alfred <strong>Beta</strong></div>
<div data-alphabetize="Alpha">Mark Unicode <strong>Alpha</strong></div>
<div data-alphabetize="Gamma">Graham <strong>Gamma</strong>-Python</div>
<div data-alphabetize="Omega">Matthew <strong>Omega</strong></div>
</div>

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>

How do I return a count in Angular for the number of divs on my page with specific values or properties?

I am working with dynamic web, this connected to websocket, then when my web load, i call a load.php (with angular directive).
This web(load.php) makes a select in mySQL (i have many tables, linked when id).
Then I make a left join in all tables and I get a unidimensinal array with info about all tables.
Next i show all data with angularjs, each table in different div, where if TABLEX_VALUE!='null' -->ng-show, eq:
<div ng-repeat="data in alldata">
<div ng-show="TABLEX_VALUE!='null'">
{{data.TABLEX_VALUE1}} - {{data.TABLEX_VALUE2}}
</div>
<div ng-show="TABLEY_VALUE!='null'">
{{data.TABLEY_VALUE1}} - {{data.TABLEY_VALUE2}}
</div>
.
.
.
.
<div ng-show="TABLEZ_VALUE!='null'">
{{data.TABLEZ_VALUE1}} - {{data.TABLEZ_VALUE2}}
</div>
</div>
How do I count all tables where TABLEX_VALUE!='null'?
Try using $filter to get all the elements with your desired values, and look for the length of the resulting array.
See the docs, and two previous questions, which are related but aren't asking the same thing.
You're looking for the JavaScript pattern:
$filter('filter')(array, expression, comparator)

Categories

Resources