Link two objects in angular - javascript

I've got 2 data sets
posts
[
{
"postId": 1,
"postContent": "Lorem Ipsum",
"user": 1
},
{
"postId": 2,
"postContent": "Lorem Ipsum",
"user": 2
},
]
and users
[
{
"user": 1,
"firstName": "John",
"lastName": "Doe"
},
{
"user": 2,
"firstName": "Johny",
"lastName": "Doey"
}
]
I am repeating all the posts and i would like to access a user data throught the $scope.post.user.firstName etc.
how should i aproach it?

You can implement a method like getUserById() with the use of Array.prototype.find() to use it when iterating over your posts.
Code in AngularJS:
angular
.module('App', [])
.controller('AppController', ['$scope', function ($scope) {
$scope.posts = [{"postId": 1,"postContent": "Lorem Ipsum","user": 1},{"postId": 2,"postContent": "Lorem Ipsum","user": 2}];
$scope.users = [{"user": 1, "firstName": "John", "lastName": "Doe"},{ "user": 2, "firstName": "Johny", "lastName": "Doey"}];
$scope.getUserById = function (id) {
return $scope.users.find(function (user) {
return id === user.user;
});
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.9/angular.min.js"></script>
<div ng-app="App" ng-controller="AppController" class="row">
<div ng-repeat="p in posts">
<p>{{p.postContent}} <i>by {{getUserById(p.user).firstName}}</i></p>
</div>
</div>

find() the matching user for each post.
Note that if you are not using ES6 features, you will need a polyfill for Object.assign() and should use regular function() {}s instead array functions.
var posts = [{"postId":1,"postContent":"LoremIpsum","user":1},{"postId":2,"postContent":"LoremIpsum","user":2}];
var users = [{"user":1,"firstName":"John","lastName":"Doe"},{"user":2,"firstName":"Johny","lastName":"Doey"}];
var out = posts.map(post => Object.assign({}, post, {
user: users.find(user => user.user === post.user)
}));
console.log(out);

You can create a function that maps each user object to your post object. Then you can access user details as $scope.post.user.first_name; Here is simple code that will make you an new object with users.
var new_object = [];
function mapUsersToPosts(users, posts){
angular.forEach(posts, function(post){
angular.forEach(users, function(user){
if(post.user_id == user.user_id){
new_object.push({
'post' : post,
'user' : user
});
}
});
});
}
Now you can loop new_object and use user data and post data in same object.

Related

Update properties of an object of an array

I have an array of objects and I need to update a few properties of a specific object inside the array and then run the findAndUpdateById call on it. I am trying to do this but its not updating and gives me an error of undefined name property. I guess I am not following the right procedure to update an update an object of javascript and because of this i need help.
Here is my array
let arr = [
{
"_id": "1234",
"customer": {
"firstName": "John",
"lastName": "Doe",
"email": "johndoe#gmail.com",
"address": "123 Caroline Street"
}
}
]
Now I am recieving parameter like this that i need to update in my object
let ctx = {
"params": {
"changeObject": {
"firstName": "Ali",
"email": "ali#gmail.com"
}
}
}
Given: "I am getting the array of object by making .find call against id and there will be only one customer object in the received array"
// Given
let arr=[{"_id":"1234","customer":{"firstName":"John","lastName":"Doe","email":"johndoe#gmail.com","address":"123 Caroline Street"}}];
let ctx={"params":{"changeObject":{"lastName":"Ali"}}};
arr[0].customer = Object.assign(arr[0].customer, ctx.params.changeObject);
console.log(arr);
I think you were using different properties changePayload and changeObject.
You may want to use the spread operator and map for this as well.
let arr = [
{
"_id": "1234",
"customer": {
"firstName": "John",
"lastName": "Doe",
"email": "johndoe#gmail.com",
"address": "123 Caroline Street"
}
}
];
let ctx = {
"params": {
"changePayload": {
"firstName": "Ali",
"email": "ali#gmail.com"
}
}
}
arr = arr.map( data => ({
...data,
customer: {...data.customer, ...ctx.params.changePayload}
}) );
console.log( arr );
NOTE: This will change all objects in your array, but that is what you were asking for.

Swap rows/indexes within a JavaScript array using AngularJS

I have a custom directive that is holding an array of JavaScript objects.
The object is a little complex and lengthy but I will display something similar to point out my problem:
A JSON.stringify of this displays the following:
[
{
"Id": 1,
"Name": "John Doe",
"EMail": "john#doe.com"
},
{
"Id": 2,
"Name": "Jim Doe",
"EMail": "jim#doe.com"
},
{
"Id": 3,
"Name": "Jeff Doe",
"EMail": "jeff#doe.com"
}
]
I am further using ng-repeat to display the values in a tabular form on my HTML.
The values are coming from an API call that fetches them from a database.
I want to swap - say the entire Object with Id 1 with the entire Object with Id 3 so that during my tabular display I can see Id 3 object details first and Id 1 object details last, without breaking any functionality.
What would be the best possible solution to do this within the frontend itself?
How about just swapping them using a temp variable?
var arr = [{"Id":1,"Name":"John Doe","EMail":"john#doe.com"},
{"Id":2,"Name":"Jim Doe","EMail":"jim#doe.com"},
{"Id":3,"Name":"Jeff Doe","EMail":"jeff#doe.com"}]
var tmpObj = arr[0];
arr[0] = arr[2];
arr[2] = tmpObj;
If you want to reverse the array, use Array.prototype.reverse()
var app = angular.module("myApp", []);
app.controller("myController", function($scope) {
var arr = [
{
"Id": 1,
"Name": "John Doe",
"EMail": "john#doe.com"
},
{
"Id": 2,
"Name": "Jim Doe",
"EMail": "jim#doe.com"
},
{
"Id": 3,
"Name": "Jeff Doe",
"EMail": "jeff#doe.com"
}
];
$scope.array = arr.reverse();
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="myController">
<div ng-repeat="item in array">
{{item.Id}} - {{item.Name}} - {{item.EMail}}
</div>
</div>
</div>

How to pass the array object in $http.get method in angularjs

I want to pass Array object in $http.get(). Previously all information is stored in data.json file, But I don't want to use file. Want to define the Array of object as $scope.data in controller.
Please find DEMO
http://plnkr.co/edit/X5ZC3UGey4Zjos7W01U1?p=preview
Working DEMO http://plnkr.co/edit/o6EeKnC8oFEq3GCRsQgp?p=preview
here we are using data.json. I want to define data inside data.json in Controller, Plz tell me how to dd
.controller('QuestionCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.questions = [];
$scope.data = {
"questions": [
{
"question": "Qw1",
"answers": [
{
"answers": "An1",
"value": 25
},
{
"answers": "An2",
"value": 50
},
{
"answers": "An3",
"value": 75
},
{
"answers": "An4",
"value": 100
}
]
},
{
"question": "Qw2",
"answers": [
{
"answers": "An1",
"value": 25
},
{
"answers": "An2",
"value": 50
},
{
"answers": "An3",
"value": 75
},
{
"answers": "An4",
"value": 100
}
]
}
]
}
$http
.get(JSON.stringify($scope.data))
.then(function(response){
$scope.questions = response.data.questions;
});
}])
I'm using this, and it works great for me
$http.get('url', {params: yourArray}).then(function (result) {
//do sth with data
});
HTTP GET request can't contain data to be sent to the server. You can add a query string to the request. $http option for it is params.
$http({
url: 'example.com',
method: "GET",
params: {...}
});
You dont need to use $http.get() if the data is directly available in controller.
You can use $scope.data instead of $scope.questions. ie in your html file use
{{data.questions[0].question}}
<h2>answer 1</h2>
<p>{{data.questions[0].answers[0].value}}</p>
<p>{{data.questions[0].answers[0].answers}}</p>
I have tried this way and it is working fine:
For example in your controller you have any array like arr variable
var data = Array;
data['Id'] = "1";
data['Name'] ="Test User";
data['UserName'] = "test_user";
data['Email'] = "test#gmail.com";
data['Address'] = "Test Address";
data['Action'] = 'Create';
To pass this array you can use like this
$scope.users = data;
The controller send an array in view page as the variable users
and you can use something like this
ng-repeat="user in users"
Note: this will work for two dimensional array and one dimensional array.
AngularJS has $http service, to get data asynchronously. So it can return any type of data(variable, array, string).
It is better to store data in some common place. Let me show factory pattern which is used for sharing data between controllers.
At first, you should create yourFactory.js file and write the following code:
(function () {
var yourFactory = function () {
var persons = [
{
id: 1,
name: 'Jon',
},
{
id: 2,
name: 'Ben',
},
{
id: 3,
name: 'Joseph',
},
{
id: 4,
name: 'Adam',
}
];
var factory = {};
factory.getPersons = function () {
return persons;
};
return factory;
};
angular.module('personsApp').factory('personsFactory', yourFactory);
}());
and some your controller can use data(just create new .js file for the following controller):
(function()
{
debugger;
var yourController=function($scope, yourFactory) {
/*alert('a1');*/
debugger;
function init() {
debugger;
$scope.yourData=yourFactory.getPersons();
}
init();
};
yourController.$inject=['$scope', 'yourFactory'];
angular.module('yourAppl').controller('yourController', yourController);
}());

compare 2 array of objects. match by ids, push object property into array

I have 2 arrays. users and posts. posts contain a property "post_by" which is the id of one of the users. I need to match the user and push the first & last name into the post object as a new property. Goal is I need to display the name of the user that made the post in a table.
note* I can use javascript, jquery, linq.js or lodash.
fiddle with json
fiddle
var users = [
{
"id": "15e640c1-a481-4997-96a7-be2d7b3fcabb",
"first_name": "Kul",
"last_name": "Srivastva",
},
{
"id": "4cada7f0-b961-422d-8cfe-4e96c1fc11dd",
"first_name": "Rudy",
"last_name": "Sanchez",
},
{
"id": "636f9c2a-9e19-44e2-be88-9dc71d705322",
"first_name": "Todd",
"last_name": "Brothers"
},
{
"id": "79823c6d-de52-4464-aa7e-a15949fb25fb",
"first_name": "Mike",
"last_name": "Piehota"
},
{
"id": "e2ecd88e-c616-499c-8087-f7315c9bf470",
"first_name": "Nick",
"last_name": "Broadhurst"
}
]
var posts = [
{
"id": 1,
"status": "Active",
"post_title": "test title",
"post_body": "test body",
"post_by": "4cada7f0-b961-422d-8cfe-4e96c1fc11dd"
},
{
"id": 2,
"status": "Fixed",
"post_title": "test title two",
"post_body": "test body two",
"post_by": "79823c6d-de52-4464-aa7e-a15949fb25fb"
}
]
https://jsfiddle.net/zy5oe25n/7/
console.log($.map(posts, function(post){
var user = $.grep(users, function(user){
return user.id === post.post_by;
})[0];
post.first_name = user.first_name;
post.last_name = user.last_name;
return post;
}));
Here's a lodash approach:
_.map(posts, function(item) {
return _.assign(
_.pick(_.find(users, { id: item.post_by }),
'first_name', 'last_name'),
item
);
});
It's using map() to map the posts array to a new array of new objects (immutable data). It's then using find() to locate the user object, and uses pick() to get the properties we need. Finally, assign() adds the post properties to the new object that pick() created.
For good measure, using linq.js.
var userMap = Enumerable.From(users).ToObject("$.id");
posts.forEach(function (post) {
var user = userMap[post.post_by];
if (user) {
post.first_name = user.first_name;
post.last_name = user.last_name;
}
});
Note, we're using the builtin forEach() for arrays, linq.js is not needed for that part.

ng-table filtering of concatenated values from scope

I created an application in AngularJs with ngTable, I'm using ngTable to display the user data and by requirements, I must use a single column in a table to filter by first and last name, which are separated in the $scope and I concatenate the result on the table cell. But I cannot filter by the concatenation.
I've tried to create a custom filter as it's outlined on http://bazalt-cms.com/ng-table/example/11 to accomplish this task, unsuccessfully so far.
I could modify the scope when the data is received, by looping through the array, but the result set is expected to be pretty large and I don't think that'd be the correct way to do it.
Below is a simplified example. Is there an 'Angular Way' to filter by the concatenated string, using a model or a filter?.
var app = angular.module('app', ['ngTable']);
app.controller('IndexCtrl', function ($scope, $filter, ngTableParams) {
$scope.people = [{
"id": 1,
"firstName": "Chuck",
"lastName": "Norris",
}, {
"id": 2,
"firstName": "John",
"lastName": "Lennon",
}, {
"id": 3,
"firstName": "Bender",
"lastName": "Rodriguez",
}];
$scope.peopleCopy = $scope.people;
$scope.mytable = new ngTableParams({
page: 1, // show first page
count: 10, // count per page
sorting: {
name: 'desc'
}
}, {
getData: function ($defer, params) {
$scope.people = angular.copy($scope.peopleCopy);
var filteredData = $filter('filter')($scope.people, params.filter());
$scope.people = $filter('orderBy')(filteredData, params.orderBy());
$defer.resolve($scope.people);
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js"></script>
<script src="http://bazalt-cms.com/assets/ng-table/0.3.0/ng-table.js"></script>
<body ng-app="app">
<div ng-controller="IndexCtrl">
<table border="1" ng-table="mytable" show-filter="true">
<tr ng-repeat="person in $data">
<td sortable="id" data-title="'Id'">{{person.id}}</td>
<!--td I want to sort by firstName + lastName -->
<td sortable="firstName" filter="{ 'firstName': 'text' }" data-title="'Name'">{{person.firstName +' '+ person.lastName}}</td>
</tr>
</table>
</div>
</body>
You can create a filter function that looks at both fields
$scope.people = [{
"id": 1,
"firstName": "Chuck",
"lastName": "Norris",
}, {
"id": 2,
"firstName": "John",
"lastName": "Lennon",
}, {
"id": 3,
"firstName": "Bender",
"lastName": "Rodriguez",
}];
$scope.filterLastAndFirst= function(person, searchParam){
return person.firstName.indexOf(searchParam) !== -1 || person.lastName.indexOf(searchParam) !== -1;
};
<li ng-repeat="item in products | filterLastAndFirst: searchParam">{{item.name}}</li>
// where $scope.searchParam is defined
Or a filter
app.filter('lastAndFirstFilter', function(){
return function(objectArray, searchParam){
var toReturn = [];
// parse the array and search for a parameter.
angular.forEach(objectArray, function(value){
if(value.lastName.indexOf(searchParam) !== -1 || value.firstName.indexOf(searchParam) !== -1)
toReturn.push(value);
});
return toReturn; // return the array
}
});
// used like this:
var filtered = $filter('lastAndFirstFilter')($scope.people, searchTerm);
Utimately, I solved the filtering by using a simple filter (shown below). that adds the value person.fullName to the current object collection used in ng-repeat by the table
$scope.getFullName = function(person) {
return person.fullName = person.name + ' ' + person.lastName;
}
and referencing it in the ngTable's ng-repeat
<tr ng-repeat="person in $data | filter:getFullName">
Then using the newly added value to the object with {{person.fullName}} in where needed (in the filter and cell value).
<td data-title="'Name'" sortable="'person.fullName'"
filter="{ 'fullName': 'text' }" header-class="ngtable-header"
class="ngtable-td">{{ person.fullName }}</td>

Categories

Resources