I'm using At.js plugin. It's working fine for a single object (demo)
var names1 = ["Jacob", "Isabella", "Ethan", "Emma", "Daniel", "Madison"];
var names = $.map(names1, function(value, i) {
return {
'id': i,
'name': value,
'email': value + '#yahoo.com'
};
});
But when I try to add multiple objects it's not working (demo). I knew the code is the problem.
I want to display the description when a user selects the name of the person using # tag.
$(function() {
$.fn.atwho.debug = true
var names1 = [{
"name": "Jacob",
"description": "description one description one description one"
},
{
"name": "Isabella",
"description": "description two description two description two"
}
];
var names = $.map(names1, function(value, description, i) {
return {
'id': i,
'name': value,
'email': description
};
});
var at_config = {
at: "#",
data: names,
headerTpl: '<div class="atwho-header">Service List <small>↑ ↓ </small></div>',
insertTpl: '${email}',
displayTpl: "<li>${name}</li>",
limit: 200
}
$inputor = $('#inputor').atwho(at_config);
$inputor.caret('pos', 47);
$inputor.focus().atwho('run');
});
The map function in Jquery does not take each element in a object as the function argument, you get the entire object (the element in the list) and you then need to extract the name, and the description. You were almost there.
$(function() {
$.fn.atwho.debug = true
var names1 = [{
"name": "Jacob",
"description": "description one description one description one"
},
{
"name": "Isabella",
"description": "description two description two description two"
}
];
var names = $.map(names1, function(value, index) { //Here I have only used value
return {
'id': index,
'name': value.name, //Here I take value.name from the object
'email': value.description //And value.description from the object
};
});
var at_config = {
at: "#",
data: names,
headerTpl: '<div class="atwho-header">Service List <small>↑ ↓ </small></div>',
insertTpl: '${email}',
displayTpl: "<li>${name}</li>",
limit: 200
}
$inputor = $('#inputor').atwho(at_config);
$inputor.caret('pos', 47);
$inputor.focus().atwho('run');
});
Related
I can't google the right solution for this for about an hour straight,
So I'm getting a response from the API that looks like this:
[
{
"Name": "name1",
"Title": "Name One",
"Children": [
{
"Name": "Name 1.1",
"Title": "Name one point one"
},
]
And I need it to fit this kind of "mold" for the data to fit in:
{
title: 'Name One',
value: 'name1',
key: '1',
children: [
{
title: 'Name one point one',
value: 'Name 1.1',
key: 'key1',
},
I am trying to achieve this using a foreach but It's not working as intended because I need to do this all in one instance of a foreach.
Here's what I gave a go to(vue2):
created() {
getData().then(response => {
const formattedResponse = []
response.forEach((el, key) => {
formattedResponse.title = response.Title
formattedResponse.name = response.Name
formattedResponse.children = response.Children
})
})
Use map over the main array and use destructuring assignment to extract the properties by key, and relabel them, and then do exactly the same with the children array. Then return the updated array of objects.
const data=[{Name:"name1",Title:"Name One",Children:[{Name:"Name 1.1",Title:"Name one point one"}]},{Name:"name2",Title:"Name Two",Children:[{Name:"Name 1.2",Title:"Name one point two"}]}];
const result = data.map((obj, key) => {
const { Title: title, Name: value } = obj;
const children = obj.Children.map(obj => {
const { Title: title, Name: value } = obj;
return { title, value, key: (key + 1).toString() };
});
return { title, value, children };
});
console.log(result);
Your API response is JSON. All you need to do is:
var resp=JSON.parse(API response);
I'm using EXTJS framework for my code.
below is my array structure:
data = [{
id: 22,
rows: [{
id: "673627",
name: "ABS",
address: "536street"
}, {
id: "333",
name: "TEST$$",
address: "536street"
}, {
id: "999",
name: "TEST$$",
address: "536street"
}]
}, {
id: 33,
rows: [{
id: "899",
name: "TES",
address: "536street"
}, {
id: "333",
name: "TEST$$",
address: "536street"
}, {
id: "999",
name: "TES673",
address: "536street"
}]
}]
Now I want to filter the name from this array, whose value I'm comparing with say "TEST$$".
I'm doing this;
Ext.each(data, function(item) {
filter = item.rows.filter(function(name) {
return name.name === "TEST$$";
}, this);
}, this);
console.log(filter);
In this case, it returns only 1 match, where as I have 3 matches for this particular value. It returns the match from the last item in the data array and hence I dont get all the matching values, any idea how this can be looped to get all values matching?
thx!
You're reassigning the filter variable on every iteration over the data array:
filter = item.rows.filter(function(name) {
return name.name === "TEST$$";
}, this);
On the last iteration, there is only one match, the one with id of 333, so that's the only one that you see after running the Ext.each. Try pushing to an external array that doesn't get overwritten instead:
const testItems = [];
Ext.each(data, function(item) {
const filtered = item.rows.filter(row => row.name === "TEST$$")
testItems.push(...filtered);
});
console.log(testItems);
Note that there's no need to pass along the this context.
Another option is to flatMap to extract all rows to a single array first:
const output = data
.flatMap(({ rows }) => rows)
.filter(({ name }) => name === 'TEST$$');
I have an empty array called result[]. A user then clicks a link which calls a function called getId() that passes the clicked id to check if it matches the id in another array called productsArray[].
Jackets
var productsArray = [
{id:0, title:"Product A",description:"description 0"},
{id:0, title:"Product B",description:"description 1"},
{id:2, title:"Product C",description:"description 2",},
{id:0, title:"Product D",description:"description 3",},
{id:4, title:"Product A",description:"description 4",},
{id:5, title:"Product A",description:"description 5",}
],
result = [];
If the user clicks the Jackets link (which has an id of 0) the 3 items in the productsArray, will get returned: Product A, B and D.
The code I have to achieve this actually works:
var output;
var container;
for(key in productsArray) {
if (productsArray[key].id == id) {
result.push(productsArray[key].title, productsArray[key].description);
}
}
container = document.getElementById('content');
output=result;
container.innerHTML=output;
<div id="content"></div>
But the problem is that ALL the data is assigned to the result[] key index:
For example:
[0]Produduct A title
[1]Product B title
[2]Product C title
What I would like to achieve a way of splitting up the data along the lines of the following:
output+= result[0].title + result[0].description
Any help appreciated.
Cheers
You could map the result and the wanted keys of the product.
function getId(id) {
document.getElementById('content').innerHTML = productsArray
.filter(function (product) {
return product.id == id;
})
.map(function (product) {
return ['title', 'description']
.map(function (key) { return product[key]; })
.join(' ');
})
.join('<br>');
}
var productsArray = [{ id: 0, title: "Product A", description: "description 0" }, { id: 0, title: "Product B", description: "description 1" }, { id: 2, title: "Product C", description: "description 2" }, { id: 0, title: "Product D", description: "description 3" }, { id: 4, title: "Product A", description: "description 4" }, { id: 5, title: "Product A", description: "description 5" }];
Jackets
<div id="content"></div>
You have to assign a variable that takes value of title and description and then push that value to array. like below code
function getId(id){
var output;
var container;
for(key in productsArray) {
if (productsArray[key].id == id) {
newObj= "" ; // assign to blank
newObj = productsArray[key].title +" "+ productsArray[key].description; //assign as per you need the format
result.push(newObj); // push it to array
}
}
container = document.getElementById('content');
output=result;
container.innerHTML=output;}
I came up with the following way to reduce my data:
data = [{ id: 99991, name: "NoData1", title: "No Data" },
{ id: 99992, name: "NoData2", title: "No Data" },
{ id: 99993, name: "NoData3", title: "No Data" }];
var dataMapName = data.reduce((rv, v) => {
rv[v.name] = v;
return rv;
}, {}) : null
Now If I want to access the id I can enter the following:
var NoData1Id = dataMapName['NoData1'].id
or
var NoData1Id = dataMapName.NoData1.id
However some of my data has spaces in the name such as:
data = [{ id: 99991, name: "NoData1", title: "No Data" },
{ id: 99992, name: "NoData2", title: "No Data" },
{ id: 99993, name: "NoData3", title: "No Data" },
{ id: 99994, name: "NoData 4", title: "No Data" },
];
Is there a way that I could change my function so that it first removed spaces from the name during the reduction so that I could still enter:
var NoData4Id = dataMapName.NoData4.id
You can use regex to remove all spaces from name.
\s will match all the space characters like tabs, spaces, etc. g flag is for matching all the spaces.
rv[v.name.replace(/\s/g, '')] = v;
Demo
Well, then just replace space with an empty string.
var dataMapName = data.reduce((rv, v) => {
rv[v.name.replace(' ', '')] = v;
return rv;
}, {}) : null
and other option is to use the data as is, just make sure to use bracket notation.
var NoData4Id = dataMapName.["NoData 4"].id
You can change key of the map while you are inserting:
data = [{ id: 99991, name: "NoData1", title: "No Data" },
{ id: 99992, name: "NoData 2", title: "No Data" },
{ id: 99993, name: "NoData3", title: "No Data" }];
var dataMapName = data.reduce((rv, v) => {
var vName = v.name.replace(/\s/g,'');
rv[vName] = v;
return rv;
}, {}) : null
I have two arrays, Users and Employments like so:
Users = [{id:1, name: "ryan"}, {id:2, name:"Julie"}]
Employments = [{user_id: 1, title: "manager"}, {user_id: 2, title: "Professor"}]
I'd like to display the Employments array in an ng-repeat like so:
<li ng-repeat="employment in Employments">
{{employment.user.name}}
</li>
How do I map the Users array to the Employments array?
If you want the employee name to get displayed based on id, the simplest way is just pass that id to a function and return the name, like as shown below
Working Demo
html
<div ng-app='myApp' ng-controller="ArrayController">
<li ng-repeat="employment in Employments">{{getEmployeeName(employment.user_id)}}
</li>
</div>
script
var app = angular.module('myApp', []);
app.controller('ArrayController', function ($scope) {
$scope.Users = [{
id: 1,
name: "ryan"
}, {
id: 2,
name: "Julie"
}];
$scope.Employments = [{
user_id: 1,
title: "manager"
}, {
user_id: 2,
title: "Professor"
}];
$scope.getEmployeeName = function (empId) {
for (var i = 0; i < $scope.Users.length; i++) {
if ($scope.Users[i].id === empId) {
return $scope.Users[i].name;
}
};
};
});
UPDATE 2
If you want to embed the User array in the Employments array, try the following stuff
$scope.Users = [{id: 1, name: "ryan"}, {id: 2, name: "Julie"}];
$scope.Employments = [{user_id: 1, title: "manager"},
{user_id: 2, title: "Professor"}
];
code for flattening Employments array by adding User properties
angular.forEach($scope.Users, function (user, userIndex) {
angular.forEach($scope.Employments, function (employee, employeeIndex) {
if (employee.user_id === user.id) {
employee.name = user.name;
}
});
});
Output
$scope.Employments = [ { user_id: 1, title: "manager", name: "ryan" },
{ user_id: 2, title: "Professor", name: "Julie" }
]
Working Demo
UPDATE 3
Code for making a nested employee structure like as shown below from $scope.Users and $scope.Employments
$scope.employees = [];
angular.forEach($scope.Employments, function (employee, employeeIndex) {
var employeeObject = {};
employeeObject.title = employee.title;
angular.forEach($scope.Users, function (user, userIndex) {
if (employee.user_id === user.id) {
employeeObject.user = user;
}
});
$scope.employees.push(employeeObject);
});
Output
[ { title: "manager", user: { "id": 1, "name": "ryan" } },
{ title: "Professor", user: { "id": 2, "name": "Julie" } }
]
Working Demo
If you wanted to match up the two following arrays purely with a template you could take the following arrays
Users = [{id:1, name: "ryan"}, {id:2, name:"Julie"}]
Employments = [{user_id: 1, title: "manager"}, {user_id: 2, title: "Professor"}]
And nest a repeat like:
<li ng-repeat="employment in Employments">
<div ng-repeat="user in Users" ng-if="user.id === employment.user_id" >
{{user.name}}:{{employment.title}}
</div>
</li>
Two more nice little thing to do to avoid any risk of getting those brackets showing on a slow page load is to use the ng-bind and prefix the attributes with data so its with the html spec
<li data-ng-repeat="employment in Employments">
<div data-ng-repeat="user in Users" data-ng-if="user.id === employment.user_id" >
<span data-ng-bind="user.name"></span>:<span data-ng-bind="employment.title"></span>
</div>
</li>
I know you didn't have the need for anything but the name, but figured a quick example of using the outer loop in the inner still could be helpful. Also this would be the case for ng-init if you needed to reference the the $index of the outer ng-repeat from the inner, but that might be more than you're looking for here.
Plunker
This sorts the users names into the employments array:
var sortUsers = function() {
var i = 0;
for (i; i < $scope.users.length; i++) {
console.log($scope.users[i].id)
for(var z = 0; z < $scope.employments.length; z++) {
if($scope.employments[z].user_id === $scope.users[i].id) {
$scope.employments[z].name = $scope.users[i].name;
}
}
}
}
HTML:
<ul>
<li ng-repeat="employment in employments">
{{employment.name}}
</li>
</ul>
I dealt similar problem yesterday. If you want to use js, have to loop twice.
I recommend to use the best way is to select in one query by join table if data come from single database.
You select User by one query, and Employment for another query in database. Then, twice ng-repeat to re-arrange. Here is my solution.
select users.*, employments.title from `users` inner join `employments` where users.id = employments.user_id;
Hope be be helpful.