Angular ng-repeat this JSON structure for user to user messaging - javascript

Very simple user to user messaging piece that I'm struggling with the interface in an app to use ng-repeat on the items.
Here is the data:
{
"ID": 4118,
"CreatedDate": "2015-08-20T03:12:50.397",
"recipient": [
{
"ID": 13,
"FirstName": "Heather",
"LastName": "Martin",
"ProfileImage": "https://../profilepictures/13"
}
],
"sender": [
{
"ID": 1046,
"FirstName": "Brad",
"LastName": "Martin",
"ProfileImage": "https://../profilepictures/1046"
}
],
"messages": [
{
"ID": 4137,
"ConversationID": 4118,
"UserID": 1046,
"Body": "hey",
"CreatedDate": "2015-08-20T14:34:42.4716233+00:00"
}
]
}
In the controller I get the conversations out of LS, one conversation is one record in LocalStorage, the JSON above will represent one conversation.
$scope.convo = JSON.parse(localStorage.getItem("convo-" + $stateParams.chatId));
Here is the structure I am trying to achieve (again, very simple, nothing fancy).
<ul>
<li class="item-avatar-left" ng-repeat="c in convo track by $index">
<img ng-src="{{c.recipient[0].ProfileImage}}" />
<p class="bubble speech">
{{c.messages[0].Body}}
</p>
</li>
</ul>
I've tried multiple variations on the ng-repeat directive.
Essentially what I'd like to achieve is just showing one <li> per each message.
Current result:
Console output of a conversation from LS:

You can try normally by ng-repeat
In controller like:
$scope.convo = [
{
"ID": 4118,
"CreatedDate": '2015-08-20T03:12:50.397',
//...... as your info
}
];
In HTML:
<ul>
<li class="item-avatar-left" ng-repeat="c in convo">
<img ng-src="{{c.recipient[0].ProfileImage}}" />
<p class="bubble speech" ng-repeat="m in c.messages">
{{m.Body}}
</p>
</li>
</ul>
NB: your $scope.convo need to be an array

Related

How to use v-for 2 times to get specific values in check-box action form?

I am new to Vue js. I am trying to do an action form for the rest of API. I don't know how to get the data of name and location only. I was trying to use slice in Array, but it does not work.
My action form:
<div class="form-group">
<label class="required"> Social Media </label>
<b-form-checkbox v-for="event in events" :key="event._id" :value="event" v-model="selected">
{{event.name}}, {{event.location}}
</b-form-checkbox>
<span class="mt-3">Selected: <strong>{{ selected }}</strong></span>
</div>
My Vue instance
export default {
data() {
return {
events: [{
"_id": "d4d81da6-b453-4a31-999f-a2ea04848ee9",
"name": "A",
"location": "US",
"__v": 0
},
{
"_id": "91205d34-4480-4e4e-bdf7-fe66e46922b0",
"name": "B",
"location": "Korea",
"__v": 0
},
{
"_id": "0b168c44-4f38-4f86-8ee6-e077333aca95",
"name": "C",
"location": "Japan",
"__v": 0
}],
selected: ''
};
}
}
The Output when checking the first option of the checkbox:
Selected: ["_id": "d4d81da6-b453-4a31-999f-a2ea04848ee9", "name": "A", "location": "US", "__v": 0]
Expected output when checking the first option of the checkbox:
Selected: [ "name": "A", "location": "US" ]
You can create the necessary structure within the :value="" assignment.
<b-form-checkbox v-for="event in events" :key="event._id" :value="{ name: event.name, location: event.location }" v-model="selected">
{{event.name}}, {{event.location}}
</b-form-checkbox>
Firstly make Selected:false boolean ... then make a button and on click it'll get to a function which will accepts a parameter, iterate your array and select an object which is matching with the parameter
private selectFun(item){this.events.filter(val=>{val._id===item._id})//and then whatever}

How to connect nested map functions inside container?

I am a little stuck in here, so basically the problem is with the nested map function.
I have main map function which provides me a list of all hotels ever added to the database.
Inside that map function, I must have a nested map of reviews for specified hotel but, the problem is
with the same keys. In main map function, I have keys like, id, name, etc. As for the nested review map, I have id, which is basically different from the id provided in main map so I'm stuck while trying to connect them.
Here's my code:
<div>
<div className='landing-container'>
<nav>
<h2>Hotel Challenge</h2>
<ul>
<li><a className="nav-link" onClick={loadHotels}>List All Hotels</a></li>
<li><Link className='nav-link' to='/dashboard'>Dashboard</Link></li>
<li><Link className='nav-link' to='/favorites'>Favorites</Link></li>
<li><a className="nav-link" onClick={handleLogout}>Logout</a></li>
</ul>
</nav>
</div>
<div className="layout-container">
<div>{hotelItems.map((item) => (
<div className="hotel-container" key={item.id}>
<div className="hotel-name">
{item.name}
<div className="hotel-location">{item.city}, {item.country}</div>
<div className="hotel-stars">
{Array(item.stars).fill(<FontAwesomeIcon className="icon-color-star" icon={faStar} />)}
</div>
<img className="hotel-image" src={item.image} />
<div className="reviews">
<button className="review-button" onClick={showHotelReviews}>Show Reviews</button>
{hotelReviews.map((review) => (
<div>
<div className="review-message">{review.id}</div>
<div className="review-likes">Liked by: <span>{review.likes}</span><sup><FontAwesomeIcon className="icon-color-likes" icon={faHeart} /></sup></div>
</div>
))}
</div>
</div>
</div>
))}</div>
</div>
</div>
I tried providing the main map key to the nested map, but that didn't work either.
All hotels in array:
[
{
"id": 42,
"name": "Courtyard by Marriott Belgrade City Center",
"city": "Belgrade",
"country": "Serbia",
"image": "http://127.0.0.1:8000/media/images/54129602.jpg",
"stars": 4,
"date": "2017-11-15 00:03:32",
"description": "Lorem Ipsum",
"price": 52.0,
"likes": 45,
"dislikes": 2,
"user": [
1,
73
],
"location": "44.8170754,20.4580087"
},
]
Reviews Array:
[
{
"id": 1,
"message": "“Very comfortable.”",
"created_at": "2020-08-13T18:10:56.240421Z",
"likes": 5,
"dislikes": 0,
"positive": true,
"author": {
"id": 1,
"first_name": "First Name",
"last_name": "Last Name"
}
}
]
It would probably be better to split this into a different components (something like Hotel). With that you can have different keys for hotels and reviews - you can keep your current ids for hotels, while using id for reviews in the Hotel component.
Probably some info on ReviewsArray is missing: a "foreign key" to Hotels. Something like:
[
{
"id": 1,
"message": "“Very comfortable.”",
"created_at": "2020-08-13T18:10:56.240421Z",
"likes": 5,
"dislikes": 0,
"positive": true,
"author": {
"id": 1,
"first_name": "First Name",
"last_name": "Last Name"
},
"hotel_id": id <------ "foreign key" id here
}
]
And, in this way, you could filter the list before map:
hotelReviews.filter((review) => review.hotel_id == item.id).map((review) => (code here))
If I understood your problem correctly, is difficult to know the hotel being reviewed given a review without this type of information. Maybe this info exist but is masked inside another information.

Want to acces object in requests array of profile in users collection

i want to create a event in which by clicking on accept in the
termplate i want to get that respective object of requests array in
profile of users collection
this profile section of my users collection (accounts-password)
{
"profile": {
"name": {
"first_name": "Vibhor",
"last_name": "Yadav"
},
"college_name": "ssit",
"gender": "MALE",
"friends": [],
"requests": [{
"id": "z6rDkvayDA5Ckoeab",
"name": "Nitin Gupta"
}],
"requested": [{
"id": "M6edD427rG9WwhfNh",
"name": "suraj Kumar"
}]
}
template to print requests
<template name = "notification">
<div id="req-main-div">
<ul>
{{# each username in reqList}}
<li>
<div id="req-user-name" value={{username.name}}>{{username.name}}</div>
<div id="accept">accept</div>
<div id="delete">delete</div>
</li>
{{/each}}
</ul>
</div>
</template>
helper to the template
Template.notification.helpers({
reqList:function () {
var User = Meteor.user();
return User.profile.requests;
}
});
the method i tried
Template.notification.events({
'click #accept':function(){
console.log(document.getElementById('req-user-name').value);
Meteor.call('accept_request',this);
}
});
i am not able to access DOM too
accept_request:function(accept){
if(!Meteor.userId())
{
throw new Meteor.Error('not-authorized','you are not signed in');
}
var user = Meteor.user();
console.log(accept);
}
iam getting this on console
undefined//for DOM of # accept
Object// for accept in accept_request method
main: ()
__proto__: Object

Fetching information from nested JSON based on unique fields using AngularJS

I have a json as following.
{
"id":14,
"discussion":8,
"parent":0,
"userid":2,
"subject":"communication skill discussion 2",
"message":"<p>hi all to communication discussion 2 </p>",
"children":[
24,
16,
15
]
},
{
"id":15,
"discussion":8,
"parent":14,
"userid":2,
"subject":"Re: communication skill discussion 2",
"message":"<p>hiiiiiiiiii</p>",
"children":[
25,
23
],
},
{
"id":23,
"discussion":8,
"parent":15,
"userid":2,
"created":1461562317,
"modified":1461562317,
"mailed":0,
"subject":"Re: communication skill discussion 2",
"message":"<p>helloooo</p>",
"children":[
],
}
I want first fetch the details whose Ids matches with the elments in children array
such as for id:14 there are 3 children 24,16,15.Then the control should go directly to id:15 and fetch details of id:15.Again id has children eg. consider id:23 which has no children and will directly print the message.
Please guide me how will I achieve this using ng-repeat of angular ?
Refer to the demo.
Please find the code below:
HTML:
<div ng-app="app" ng-controller="test">
<div ng-repeat="(key,value) in data">
{{key + 1}}) --
<span ng-if="value.children.length > 0">
{{value.children}}
</span>
<span ng-if="!(value.children.length > 0)">
No children found!!
</span>
</div>
</div>
JS:
var app = angular.module('app', []);
app.controller('test', function($scope) {
$scope.data = [{
"id": 14,
"discussion": 8,
"parent": 0,
"userid": 2,
"subject": "communication skill discussion 2",
"message": "<p>hi all to communication discussion 2 </p>",
"children": [
24,
16,
15
]
}, {
"id": 15,
"discussion": 8,
"parent": 14,
"userid": 2,
"subject": "Re: communication skill discussion 2",
"message": "<p>hiiiiiiiiii</p>",
"children": [
25,
23
],
}, {
"id": 23,
"discussion": 8,
"parent": 15,
"userid": 2,
"created": 1461562317,
"modified": 1461562317,
"mailed": 0,
"subject": "Re: communication skill discussion 2",
"message": "<p>helloooo</p>",
"children": [
],
}];
});
UPDATE: As per the request
Demo
HTML:
<div ng-app="app" ng-controller="test">
<div ng-repeat="(key,value) in data">
[{{key + 1}}] --
<div ng-if="value.children.length > 0">
<div ng-repeat="item in value.children">
<span>{{item}}</span> <span class="green" ng-bind-html="getMessage(item)"></span>
</div>
</div>
<span ng-if="!(value.children.length > 0)">
No children found!!
</span>
<br />
</div>
</div>
JS:
$scope.getMessage = function(itemId) {
var flag = true;
var msg;
angular.forEach($scope.data, function(value, key) {
if (flag && value.id == itemId) {
flag = false;
msg = value.message;
}
});
return $sce.trustAsHtml(msg);
}
CSS:
.green {
color: green;
}
Use ng-repeat to display the records.
<ul ng:controller="Cntl">
<li ng:repeat="item in data">
{{item.subject}}: Parent
<ul>
<li ng:repeat="child in item.children">{{child}} : Children
</li>
</ul>
</li>
This is one of the way to display in html. Based on your page design ng-repeat will change.
You can use lodash or underscore _.where:
<div ng:controller="Cntl">
<div ng:repeat="item in data">
{{item.subject}}<br/>
Children
<div ng:repeat="child in item.children">{{_.where(data, {id:child});}}
</div>
</div>
First you need to restructure your json into a tree structure. May be you want to have a look at this post. Then you have to recursively add templates

Treeview like representation

Lets say using the following data I would like to create a treeview-like representation.
var demoData = [
{"name": "person1", "parent": ""},
{"name": "person2", "parent": "person1"},
{"name": "person3", "parent": "person1"},
{"name": "person4", "parent": "person2"},
{"name": "person5", "parent": "person3"}
];
The output should be something like this.
person1
|--person2
| |--person4
|--person3
|--person5
How would I do this with AngularJS. I know how to do this lets say in C# with a recursive function but cannot get my head around how to do this in AngularJS.
I have looked at other questions on SO but the data there was formatted in a different way so that the child entities were directly in the parent entity.
Generally (like in C#) you can achieve recursive call by using ng-include.
One node calls ng-include="'tree_item_renderer' for each child.
Something like:
<script type="text/ng-template" id="tree_item_renderer">
<span>
{{showNode(data)}}
</span>
<ul class="some" ng-show="data.show">
<li ng-repeat="data in data.nodes"
ng-include="'tree_item_renderer'" tree-node></li>
</ul>
</script>
And root call:
<ul>
<li ng-repeat="data in displayTree"
ng-include="'tree_item_renderer'"></li>
</ul>
The basic demo you can find here in Plunker

Categories

Resources