AngularJs Separating Results into Divs by column value - javascript

I have been struggling to figure out the logic on how to display my results into separate divs in this case bootstrap col-md-4's. It is for a chat messaging app that i'm attempting to build. There is rooms and messages I want each room to only display it's messages grouped together into divs.
My results($scope.messages) look like:
messages = [
{"room_id":1,"message_id":2,"message_content":"hiiii","message_time":"2015-11-28 23:22:57","user_name":"Aaaa1aa"},
{"room_id":1,"message_id":1,"message_content":"hi there","message_time":"2015-11-28 23:22:40","user_name":"aaaa2aa"},
{"room_id":2,"message_id":3,"message_content":"hyyy","message_time":"2015-11-28 23:23:07","user_name":"Guest"},
{"room_id":2,"message_id":4,"message_content":"aaaaa","message_time":"2015-11-28 23:23:20","user_name":"aaaa2aa"}
];
I want to display each results set grouped by the room_id column so when repeating through the data this set would look like so
<div class="col-md-4"> Room Id - 1
aaaa2aa - hi there
Aaaa1aa - hiiii
</div>
<div class="col-md-4"> Room Id - 2
Guest - hyyy
aaaa2aa - aaaaa
</div>
I thought something like this might work after trying several other options but it is not providing any results.
<div class="col-md-4" ng-repeat="data in messages">
<div ng-repeat="data in data[$index]">
{{data.user_name}}
{{data.message_content}}
</div>
</div>
Thanks for any help.
This is what worked for me, but you must first add the module filter as an dependency:
<div class="col-md-4" ng-repeat="data in messages | groupBy: 'room_id'">
{{data[$index].room_id}}
<div ng-repeat="data in data">
{{data.user_name}}
{{data.message_content}}
</div>
</div>

You can use groupBy to group the results:
(k, v) in messages | groupBy: 'room_id'
Another solution would be to use filter:
<div class="col-md-4" ng-repeat="data in messages | filter: '{'room_id': 2}'"> //show only items with room_id set to 2 and so on
</div>
However, this method will be repetitive and redundant.

Related

Display JSON Objects vertically on a web page using table/flexboxes/divs and javascript?

I have a JSON with multiple products. All these products are defined by data. I would like to loop through this JSON and place these products side by side on a web page to compare them together. I think of a structure first organized in columns and then rows :
So far I can do this easily with HTML divs and flexboxes. Something like :
<div style="display:flex">
<div id="Sidebar">
<div class="Data_1">...</div>
<div class="Data_2">...</div>
<div class="Data_3">...</div>
<div class="Data_4">...</div>
...
</div>
<div id="Product_A">
<div class="Data_1">...</div>
<div class="Data_2">...</div>
<div class="Data_3">...</div>
<div class="Data_4">...</div>
...
</div>
<div id="Product_B">
<div class="Data_1">...</div>
<div class="Data_2">...</div>
<div class="Data_3">...</div>
<div class="Data_4">...</div>
...
</div>
<div id="Product_C">
<div class="Data_1">...</div>
<div class="Data_2">...</div>
<div class="Data_3">...</div>
<div class="Data_4">...</div>
...
</div>
</div>
But, if one of the product features contains a long string, I would like the height of all adjacent cells of the other products and the sidebar to fit also in height.
I know I can achieve a such structure with an HTML table, but it's not convenient to dynamically add/remove products or make them draggable as tables are first organized in rows. I would like to be able to add products, remove products, drag them, filter them, sort them... I think that a table structure is not suitable.
My questions :
If using tables, is there a way to first organize a table in columns then rows?
If using divs or flexboxes, how can I align all the product lines in height?
Any other good idea to structure such content or use javascript to achieve this easily?
You can achieve this with using max-height and iterate products in div or ul>li.
Show code to get more help.
Probably put a min-height on the product container and then iterate through your json with something like.
products.map(product =>
<div>
<span> product.name </span>
</div>
)
The product container div should adapt its own contents if the json data is longer than what you are waiting.

Is there a way to show a div inside a div that has a false v-if statement

I am using Laravel 6 and Vue.js 2.
I am using a for loop to loop through users and display their info in div's as seen below.
I have the Category names stored in user.pivot.demo2. The users are arranged by category via lodash
_.orderBy(this.category.users, ['pivot.demo2', 'pivot.demo3'])
I need the div with the class of row to only display once for each category. I have the category name set to only display if the category name is the first in the list or does not match the previous name. This separates all the users by category when displaying and puts a the category caption on top of their prospective divs and works just fine. But I need the outer div with a class of row to only be made once per category then filled with the users div that has a class of col-lg-4.
In Laravel's Blade I would just use something like
#if(category != the-same-category)
<div class="row">
#endif
if (category == the-same-category)
<div class="col-lg-4">{{ User.name }} </div>
#endif
#if(category != the-same-category)
</div>
#endif
That would allow for the div with a class of row to only show once per category but the inner divs with the class of col-lg-4 to repeat on every loop. It would also close the div at the end of the condition and each category would have their own divs with the user inside of a single row div. I don't seem to be able to find a Vue.js option that will allow this type of behavior. Can anyone suggest a JavaScript or Vue.js solution?
What I have so far is the code below
<div class="outer-div text-center" v-for="(user, index) in the_category.users" :key="user.id">
<div v-if="index === 0 || user.pivot.demo2 != the_category.users[index -1].pivot.demo2">
<div class="text-center header-one">
<h2>{{ user.pivot.demo2 }}</h2>
</div>
<hr />
</div>
<div class="row d-flex justify-content-center"> // display once per category
<div class="outer-profile-div col-md-4"> // display every loop
<div class="user-name text-center">{{ user.name }}</div>
<div class="user-title text-center">{{ user.title }}</div>
</div>
</div>
My overall goal is to display the (.outer-profile-div)'s next o each other and wrap like typical bootstrap divs inside a .row while maintaining the responsive nature of bootstrap. I don't mind using CSS, JavaScript, Vue.js or whatever will deliver the desired results.
I think you are probably looking for something like this. With this code you can keep a parent element while looping only the childs. It gives you the possibilty to use the conditional directives on the childs due to the template tag had became the parent.
-Example from vue-js docs-
Try it to your problem and tell me if it solves it
<ul>
<template v-for="item in items">
<li>{{ item.msg }}</li>
<li class="divider" role="presentation"></li>
</template>
</ul>

ng-repeat on two (or more) rows

My array:
$scope.data = [1,2,3,4,5,6,7,8,9,10];
My HTML:
<div ng-repeat="item in data track by $index">{{item}}</span>
This will output, as expected: 12345678910.
But I want to display the array over two rows, as in the following sample:
12345 // break here
678910
I run some functions on this array, so I don't want to split the array into two smaller ones, cause that would mean I have to run these other functions twice as often. I have looked into the 'start end' part of ngRepeat, but honestly, I don't understand how it works, thoughts?
Note: this is an ionic application, if that matters.
Edit: I can't get the suggested answers to work, I though I could dumb down my code, and make it work, but no. this is my full html ng-repeat code:
<div class="row">
<div class="col" ng-repeat="item in data track by $index">
{{item}}
<br ng-if="$index == 4">
</div>
</div>
This did not work, how come? Anything with row or col?
You could use ng-if to insert a new line when the $index is equal to 4:
<div class="col">
<span ng-repeat="item in data track by $index">
{{item}}
<br ng-if="$index==4">
</span>
</div>
Here, we also move the ng-repeat to a span element inside the div. This solves any potential issues which may arise from the styling applied to the div.
You could also experiment with item.$middle.
item.$middle: true if the repeated element is between the first and last in the iterator
https://docs.angularjs.org/api/ng/directive/ngRepeat
<div ng-repeat="item in data track by $index">
{{item}} <br ng-if="item.$middle" />
</div>
?

angular ng-repeat, randomize orderBy

I am trying have my angular ng-repeat randomize the items when they appear. The random function I am currently using is below, however when i use this function I get a infdig, causing all sorts of problems. I dont want to do the randomize in the controller because both of these ng-repeats come from the same entry where there is a url and a name but the entry id is in both instances so it would be easier if I dont have to create separate arrays. So does anyone know of a random filter that can be used for this, that wont give me the infdig problems?
$scope.random = function(){
return 0.5 - Math.random();
};
<div ng-repeat="actor in actors | orderBy:random">
<div class="col-md-2">
<div class='imageDropTo'>
<img class='imageDropTo' src={{actor.url}} data-id= {{actor.id}}>
</div>
</div>
</div>
<div ng-repeat="actor in actors | orderBy:random">
<div class='col-md-2'>
<p id='{{actor.id}}' class='namesToDrag'> {{actor.name}} </p>
</div>
</div>

ng-repeat not working consistently with arrays of items

I have two arrays of strings that I want to repeat within my page. Here are the arrays (infoData and modelData) in the debugger:
Screenshot of arrays in Chrome inspector:
Here is my html:
<div ng-repeat="info in pTab.infoData">
<p>{{info}}</p>
</div>
<div ng-repeat="stats in pTab.modelData">
<p>{{stats}}</p>
</div>
However the page only displays the contents of infoData as shown below:
XPE
www.sampleurl.com
Sample summary has nulla quis lorem ut libero malesuada feugiat...
My question is why does this happen and how can I get the elements of the second array to display like the first?
Here is some additional info that may be useful to you. As I was trying out different things this struck me as interesting:
The following HTML:
<div ng-repeat="info in pTab.infoData">
<p>{{pTab.infoData}}</p>
</div>
<div ng-repeat="stats in pTab.modelData">
<p>{{pTab.modelData}}</p>
</div>
displays the infoData array in square brackets as a string 3 times (infoData has a length of 3).While the following HTML:
<div ng-repeat="info in pTab.infoData">
<p>{{pTab.modelData}}</p>
</div>
<div ng-repeat="stats in pTab.modelData">
<p>{{pTab.infoData}}</p>
</div>
displays the modelData array in square brackets as a string 3 times.
Is there something wrong with the <div ng-repeat="stats in pTab.modelData">? Because whatever is in that div never repeats, even if I move that div ahead of the <div ng-repeat="stats in pTab.modelData">
If I'm being unclear or you'd like to see more of the code, please let me know. Thank you very much for your time.
If you look in browser console you can see error like this
Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: stats in pTab.modelData, Duplicate key: string:0.1 mg, Duplicate value: 0.1 mg
So, you have duplicated items in your second array, and for resolve this error should use track by expression, in this case enough $index
<div ng-repeat="stats in pTab.modelData track by $index">
A bit more about it you can see in doc: Tracking and Duplicates
angular.module('app', [])
.controller('ctrl', function($scope) {
$scope.pTab = {
modelData: [
'0.1 mg',
'0.1 mg',
'0.1 mg'
]
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller='ctrl'>
<h1>Hello Plunker!</h1>
<div ng-repeat="stats in pTab.modelData track by $index">
<p>{{stats}}</p>
</div>
</div>

Categories