angularjs: resolve value from key pair - javascript

Is there any easy way to find a key in array and return its value instead of the key with angularjs (maybe by using expressions)?
right now, i do something like this:
vm.topics = [{id:1,value:"a"} , {id:2,value:"b"} , {id:3,value:"c"}];
vm.tickets= [{topic:2,summary:"summary 1"} , {topic:1,summary:"summary 2"}];
vm.getTopicName = function (id) {
for (int t=0 ; t<vm.topics.length ; t++)
if (vm.topics[t].id == id)
return vm.topics[t].value;
return id;
};
and in html part:
<tr data-ng-repeat="item in vm.tickets">
<td>{{vm.getTopicName(item.topic)}}</td>
<td>{{item.summary}}</td>
</tr>
Is there anything like
<td>{{item.topic | id as value in vm.topics}}</td>
Funny example, but i think it shows the point.
--- UPDATE ---
as #jantimon mentioned in comments, one way would be to change list to an object of real key pairs and simplify everything:
vm.topics1 = {};
for (var i=0; i < vm.topics.length; i++) {
var t = vm.topics[i];
vm.topics1[t.id] = t.value;
}
and HTML simply changes to:
<td>{{vm.topics1(item.topic)}}</td>

Actually you use two different arrays and from your comment (ajax call) I would create new array in Service that merges topics and tickets, something like:
[... ,
{
topic:2,
summary:"summary 1",
ticket_value: "b"
},
... ]
So controller should only draw it (without additional logic). This way will reduce watchers from your ng-repeat loop and you don't need to call (rebuild) getTopicName()
This is a right way I think,
To simplify your example, if you use Underscorejs library, you can write:
<td>{{topics[_.findIndex(topics, {id: item.topic})].value}}</td>
Demo in Fiddle
HTML
<div data-ng-repeat="item in tickets">
<td>{{topics[_.findIndex(topics, {id: item.topic})].value}} </td>
</div>
JS
$scope._ = _;
$scope.topics = [{id:1,value:"a"} , {id:2,value:"b"} , {id:3,value:"c"}];
$scope.tickets = [{topic:2,summary:"summary 1"} , {topic:1,summary:"summary 2"}];
**As a side note, try to avoid calling methods from HTML like:
<td>{{vm.getTopicName(item.topic)}}</td>

Related

Build a JSON structure for key and value pairs, where the keys changes for each item?

I am using SweetAlert2, and I need to create the options which will be populated in a select box for that. I know that I can use the "inputOptions" field for that, however, and I looked at their example (from their site) below :
inputOptions: {
'SRB': 'Serbia',
'UKR': 'Ukraine',
'HRV': 'Croatia'
},
Now, that is great and all, when you have a fixed set of data which is hard coded. However, in my use case, I need to be able to pull these in from a database, and my API does that already via a REST endpoint, and lets say I get it back in the following structure :
[
{"key": "SRB", "value":"Serbia"},
{"key": "UKR", "value":"Ukraine"},
{"key": "SRB", "value":"Croatia"}
]
Is there an easy way to convert the bottom format to the top?
I tried iterating over it, creating a var for each one, as follows :
var items = JSON.parse(listFromAPI);
for (var item in items)
{
var test = { item.key : item.value };
}
but that didn't seem to work? I could really use some help here.
Thanks in advance!
You can iterate over your base object and create the inputOptions as you want:
var base_format = [
{"key": "SRB", "value":"Serbia"},
{"key": "UKR", "value":"Ukraine"},
{"key": "HRV", "value":"Croatia"}
];
var inputOptions = {};
for (item of base_format)
inputOptions[item.key] = item.value;
console.log(inputOptions);
Can you try this:
var items = JSON.parse(listFromAPI);
for (var item in items)
{
var test = { items[item].key : items[item].value };
}
instead of
var items = JSON.parse(listFromAPI);
for (var item in items)
{
var test = { item.key : item.value };
}
Trying to make it as close to your existing code as possible.

Angular retrieve specific data into $scope variable is not working

I initialize here
$scope.statuses = [];
Then if I simply set the data from $http.get to the $scope variable, that "works" but I need to filter it down more.
$scope.statuses = result.data.Devices;
console.log($scope.statuses);
That returns the array of data like this in dev tools console output
0: Object
$$hashKey
:
"object:5"
Aid
:
"oAAABTUAAg=="
DKiIndex
:
"DKi00000002"
DefaultPayload
:
"C:\ProgramData\"
DeviceId
:
"00022B9A000000010001"
DeviceStatus
:
3
ManifestIdList
:
Array[3]
PendingManifestId
:
null
PendingTimeStamp
:
"0001-01-01T00:00:00"
Sha
:
"R2tiZRQgY/iohXZt5O4HaQwtVe/adWU2VOcKaelJ3Us="
StagedManifestIdList
:
Array[0]
However I only WANT some specific data
$scope.statuses = result.data.Devices.DeviceStatus;
Why does it say 'undefined' and how do I do this?
So 0: Object DeviceStatus is there.. :/
<div ng-app="app" ng-controller="DeviceController as vm">
...
<tr ng-repeat="device in vm.devices">
<td>{{device.DeviceId}}</td>
<td>{{device.DeviceStatus}}</td>
<td>{{device.Aid}}</td>
<td>{{device.Sha}}</td>
</tr>
...
Essentially I wish to manipulate the data in Javascript /angular (.js) before it makes it to the ng-repeat loop
Thus is $scope even the proper thing to even be using?
I know that I have some data to change for example
Some data in a field was surrounded by [] e.g. [01,02,03] so doing
{{ device.aid.join(',') }} would "fix" the [] issue but i need to have some function like this? where can i use this?
// usage {{displayArchived(item.archives)}}
$scope.displayArchived = function(archives){
return (archives.length > 0) ? archives.join(',') : 'none';
};
Then will a "let" help for numbers of DeviceStatus?
let statuses = ['Old Device', 'New Device', 'Activated', 'Unactivated'];
In this instance, result.data.Devices is an array of objects that looks something like this:
[
{DeviceId : "00022B9A000000010001" DeviceStatus : 3 .... },
{DeviceId : "00022B9A000030011111" DeviceStatus : 9 ...},
....
]
So when you try to get result.data.Devices.DeviceStatus, there is no array element called DeviceStatus, which is why you are getting back undefined.
You will need to iterate through the array of Devices to get a specific Device's DeviceStatus:
angular.forEach(result.data.Devices, function(value, index){
$scope.statuses.push(value.DeviceStatus);
});
or you can access directly if you know which device you want:
var index = 1;
$scope.statuses = result.data.Devices[index].DeviceStatus;
EDIT:
If you want to get all of the devices and display {{ device.DeviceStatus }} with your template, here is a solution:
Code:
$scope.devices = result.data.Devices;
Template:
<div ng-repeat="device in devices">
{{ device.DeviceStatus }}
</div>
In our code, we assign the request.data.Devices array to $scope.devices. Then in the template, we use ng-repeat to go through each device in $scope.devices and display the device's DeviceStatus.
EDIT2:
In order to match the DeviceStatus to it's actual name, you can create a custom filter.
In your code create the filter:
app.filter('deviceStatus', function () {
return function (status_id) {
var statuses = ['Old Device', 'New Device', 'Activated', 'Unactivated'];
return statuses[status_id];
};
});
You can use the new filter in your template now:
<td>{{device.DeviceId | deviceStatus}}</td>
We pipe the DeviceId into our custom deviceStatus filter in order to get the correct status name in the template.

Get keys from javascript array

Hello i have selectbox to show from javascript array.
<h6><strong>Brand</strong></h6>
<select data-placeholder="Brand..." multiple id="brand" style="width:200px;height:50px;margin: 0;">
<script language="javascript">print_brand1("brand");</script>
</select>
But when i choose one of selectbox data then it get values. Here is javascript code
var brand_arr = new Array(
1:"Acer",
2:"Dell"
);
function print_brand1(brand_id){
var option_str = document.getElementById(brand_id);
option_str.length=0;
option_str.selectedIndex = 0;
for (var i=0; i<brand_arr.length; i++) {
option_str.options[option_str.length] = new Option(brand_arr[i],brand_arr[i]);
}
}
How do i get keys (not values) when i choose one of selectbox data?
Your code will not work in its current state, however if you insist on keeping your current array structure you would need:
var brand_arr = {
1: "Acer",
2: "Dell"
};
Which syntactically makes little sense, assigning a key of 1/2 makes little sense when you could just get this number by using the current index + 1.
Note that with the changes above, in order to assign the keys 1 and 2 we are having to iterate over a Javascript Object and not a Javascript Array.
If you wanted to print 1 and 2 you could then do:
for(var k in brand_arr) {
if(brand_arr.hasOwnProperty(k)) {
console.log(k); // key
console.log(brand_arr[k]); // value
}
}
Although this answers your problem, I would still consider the structure of your data, it would make much more sense to have something like:
var brand_arr = [
{ brand: 'Acer', price: 200 },
{ brand: 'Dell', price: 200 }
];
Note how in the above example we can add extra details about that brand in the JSON. We could then iterate over the brand array to get more detail about each brand in a much more readable format opposed to a user assigned index and its name.

Create an Angularjs Filter with two file json

I'm new with angular and I have a problem with a filter.
I have two different file json like this:
[
{
"IdPers": "1067",
"CognNome": "JANE SMITH",
"Sex": "F"
},
{
"IdPers": "1093",
"CognNome": "JOHN SMITH",
"Sex": "M"
}
]
and:
[
{
"IdPers": "1067",
"DescRuol": "Membro"
},
{
"IdPers": "163",
"DescRuol": "Membro"
}
]
I Put a working Plunker: http://plnkr.co/edit/1xkyxRallRGtj83fSteg?p=preview
I have to create a filter with the field "DescRuol" which is in the file "OutCommissioni.json", the two file have the same field "id". I thought that I can do like a join but I can't make something that works! Thanks for any help
For future readers, please ignore my other answer - I mis-understood the question and worked out the details with OP in the comments there.
To have a select box with multiple options using the same value, first thing is to not use the id as the direct value that the select box will use - instead reference the object directly:
<select data-ng-options="item as item.DescRuol for item in OutCommissioni" id="DescRuol" data-ng-model="filter.IdPers" class="form-control input-sm"></select>
"item as item.DescRuol" will use the object itself as the model value, rather than just the id value.
Next, rather than using the "filter" object directly in the filter, provide a new object which contains the values you need from your filter object:
<tr data-ng-repeat="Person in OutAnagrafica|filter:{Sex:filter.Sex,IdPers:filter.IdPers.IdPers}">
Working example here: http://plnkr.co/edit/gMvuNny99b8aV66C8GAw?p=preview
Edit: ignore this answer - I misunderstood the question. New answer submitted with final details after I worked out what OP really wanted in the comments of this answer.
After fetching data from each file, normalize the difference in properties by assigning the relevant differing field to a common property, and append both sets of data to a single array.
var App = angular.module('App', []);
App.controller("OutAnCtrl", function ($http, $scope) {
$scope.data = [];
$http.get('OutAnagrafica.json')
.success(function (data) {
data.forEach(function(item) {
item.name = item.CognNome;
});
$scope.data.push.apply($scope.data, data);
});
$http.get('OutCommissioni.json')
.success(function (data) {
data.forEach(function(item) {
item.name = item.DescRuol;
});
$scope.data.push.apply($scope.data, data);
});
$scope.clearBox = function () {
$scope.filter = "";
};
});
Then finally change your repeater to use the merged data object "data" and the common property name.
<tr data-ng-repeat="Person in data|filter:filter">
<td>{{Person.IdPers}}</td>
<td>{{Person.name}}</td>
<td>{{Person.Sex}}</td>
</tr>
updated example: http://plnkr.co/edit/03rwNY7eLX9i9VCTHz7Z?p=preview
Edit: I probably mis-understood and you probably don't need those properties merged. The key part is just to append both arrays to a single array using Array.push.apply
// Create initial array
$scope.data = [];
// Append some arrays
$scope.data.push.apply($scope.data, [1,2,3]);
$scope.data.push.apply($scope.data, [4,5,6]);
// $scope.data will now contain [1,2,3,4,5,6]
Edit: I think this is what you're looking for?
http://plnkr.co/edit/jvyXlpv2iBh2n4pZ1miv?p=preview
<label for="DescRuol">DescRuol:</label>
<select data-ng-options="item.IdPers as item.DescRuol for item in OutCommissioni" id="DescRuol" data-ng-model="filter.IdPers" class="form-control input-sm"></select>

Push data into object AngularJS

I have several checkboxes that you can click on. For every checkbox you click on, an ID, that is connected to the checkbox, is pushed into an array:
HTML:
<tr ng-repeat="info in test">
<td>{{info.stracka}}</td><td>{{info.tid}}</td>
<td><input type="checkbox" id="{{info.id}}" class="checkboxfisk" ng-click="testa(info.id)">
</tr>
Controller:
$scope.testa = function(id) { //När vi klickar i de olika checkboxarna, så fyllas arrayen med dessa
$scope.checkboxes.push(id);
console.log($scope.checkboxes);
};
After this, I'm supposed to send this array containing the ID's to my backend. However, I want to send this Id's in an Object, instead of an array. How can I "push" data, like I do above, into and Object?
You can't push data into object. Consider object as an collection of key value pair. For every value you want to store into object, you need a key. That's why I was asking about your server side object.
So, in your case, before storing data into an object, i need a key. So, I have to do this like this
var testa = function(id){
checkbox[id]=id;
}
This code would definitely store your keys in the object, but look at this.
Object {5: 5, 6: 6}
This is really how the values are stored.
If you use array instead, your working would be simplified a lot on server side.
I am not sure why you need that but one possible solution is
Add name to your checkbox
<input type="checkbox" id="{{info.id}}" class="checkboxfisk" ng-click="testa(info.id, 'UNIQUE_NAME')">
init check boxes to object
$scope.checkboxes = {};
then modify you function
$scope.testa = function(id, name) {
$scope.checkboxes[name] = id;
console.log($scope.checkboxes);
};
While not exactly answering your question about "pushing" - since you cannot push to an object, you could convert your array to object just before sending it using this.
function toObject(arr) {
var rv = {};
for (var i = 0; i < arr.length; ++i)
if (arr[i] !== undefined) rv[i] = arr[i];
return rv;
}
In your example, you would do something like
$scope.checkboxesObject = toObject($scope.checkboxes);
and then send this new $scope.checkboxesObject.
However, make sure you really are "supposed" to send this to backend as an object.

Categories