Angular retrieve specific data into $scope variable is not working - javascript

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.

Related

How to get a value from an array using ID name in Angular?

I am getting value form API graduated and I want to print original text from below array.
API Response
Current Result as below image
.ts file
levelEducation = [
{id: "not-graduated", name: "OTHERS.NotGraduated"},
{id: "graduated", name: "OTHERS.Graduation"},
{id: "master", name: "OTHERS.Master"},
{id: "doctorate", name: "OTHERS.Doctorate"},
];
HTML file code
<div class="form-field">
<label>{{'JOBAPPLICATION.LevelOfEducation' | translate}}</label>
<h5>{{userData.livello_studi ? userData.livello_studi : '-'}}</h5>
<h5 *ngFor="let item of levelEducation">{{(item.name ? item.name : '-' ) | translate}}</h5>
</div>
So I need to value "OTHERS.Graduation" using ID name graduated in angular.
The best option is to use a map between livello_studi value and the display value that you want.
I guess OTHERS is an enum, so first you'll need to define the map data.
levelEducation = new Map([
["not-graduated", OTHERS.NotGraduated],
["graduated", OTHERS.Graduation],
["master", OTHERS.Master],
["doctorate", OTHERS.Doctorate],
]);
To get data from the map you do it like this
levelEducation.get(userData.livello_studi); // this will return undefined if the item is not found
So you could do this in the template to get the data:
<h5>{{levelEducation.get(userData.livello_studi) || '-'}}</h5>
(or move this code into a function for cleanliness)
If you want to map the values from graduated to Graduation you can solve this with a map.
Assumed you have n values and this is not an editable input.
let map = new Map();
map.set("graduated" ","Graduation");
map.set("not-graduated","Not graduated");
....
and later when you need to display your value you can write a function which displays your displayabletext when you need it.
return map.get("graduated");

Angular 1.5 - How to add element to a scoped array

I have an Angular controller that defines a scoped variable that consist of an array of objects. Each object is a tagName and its value is a list of services associated to those tags:
$scope.recordedServices = [{"myTag" : [{ url : "http://service0"}, { url : "http://service1" }] }];
After the page is loaded {{recordedServices}} prints correctly:
[{"myTag":[{"url":"http://service0"},{"url":"http://service1"}]}]
In that controller I have a replaceList function that replaces the whole $scoped.recordedServices list:
$scope.replaceList = function(){
$scope.recordedServices = [ {"myTag" : [{url:"http://replacedList"}] }];
}
When calling it, everything works as expected, {{recordedServices}} is now:
[{"myTag":[{"url":"http://replacedList"}]}]
Now the problem. What I really want to do is add a new service to "myTag":
$scope.addToList = function(){
$scope.recordedServices["myTag"].push({url:"http://addedService"});
}
But it fails because $scope.recordedServices["myTag"] doesn't exist, the actual structure of the $scoped.recordedServices list is:
$scope.recordedServices: Array[1]
0 : Object
$$hashKey : "object:33"
myTag : Array[1]
0 : Object
$$hashKey : "object:36"
url : "http://replacedList"
What is the correct (Angular) way to add an element to that array?
UPDATE:
One possible solution would be doing:
$scope.addToList2 = function(){
if($scope.recordedServices[0] == null){
$scope.recordedServices[0] = [];
}
if($scope.recordedServices[0]["myTag"] == null){
$scope.recordedServices[0]["myTag"] = [];
}
$scope.recordedServices[0]["myTag"].push({url:"http://addedService"});
}
But this works only if $scope.recordedServices was initialized in the controller (for instance: $scope.recordedServices = [{"myTag" : [{ url : "http://service0"}, { url : "http://service1" }] }];). However if initially it is $scope.recordedServices = [] it doesn't work.
{{recordedServices}} prints [[]]
Inspecting the variable the content is as follows. It looks similar with the only differenced that myTag[0] doesn't contain $$hashKey.
$scope.recordedServices: Array[1]
0 : Array[0]
$$hashKey : "object:68"
length : 0
myTag : Array[1]
0 : Object
url : "http://addedService"
$scope.recordedServices is an array. You should use an index:
Change this:
$scope.recordedServices["myTag"].push({url:"http://addedService"});
to this:
$scope.recordedServices[0]["myTag"].push({url:"http://addedService"});
UPDATE
You can check if it is empty, if so, add myTag object too:
if ($scope.recordedServices.length == 0){
$scope.recordedServices.push({"myTag": [{url:"http://addedService"}]});
}else{
$scope.recordedServices[0]["myTag"].push({url:"http://addedService"});
}
You can define your $scope.recordedServices=[] as an empty array inside your controller. So now you can play with it inside the controller and view as you wish.
Push new record like this -
$scope.addToList = function(){
$scope.recordedServices.push({url:"http://addedService"});
}

angularjs: resolve value from key pair

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>

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>

How to choose which field to display in ng-tags-input autocomplete?

from documentation:
<tags-input>
<auto-complete
source="{expression}"
>
</auto-complete>
</tags-input>
The result of the expression must be a promise that eventually resolves to an array of objects.
$scope.loadSuperheroes = function(query) {
// An arrays of strings here will also be converted into an
// array of objects
return $http.get('superheroes.json');
};
But I have already have an array of objects in $scope. But with a different structure:
$scope.superheroes = [{"id":1, "name":"Batman"}, {"id":2, "name":"Superman"}]
How to say in html to use list from $scope.superheroes.name ?
You can change the property used to display the tag text by setting the displayProperty property:
<tags-input ng-model="tags" display-property="name"></tags-input>
That property will also be used by the autocomplete directive to display the returned suggestions.
As described in the docs : http://mbenford.github.io/ngTagsInput/gettingstarted
NgTagsInput can perform autocomplete on an array of basic items (I asked it on GitHub to the creator of that directive months ago).
So I'll think you will have :
to reconstruct your array of objects to something like this : [{ text: 'Tag1' }, { text: 'Tag2' }, { text: 'Tag3' }]
Then, you must use the $query as parameter of your loadSuperheroes() method (as $query is the text that is being typed.
So, the HTML :
<tags-input ng-model="filteredsuperheroes">
<auto-complete
source="loadSuperheroes($query)"
>
</auto-complete>
</tags-input>
Then, the JS (Angular) part :
$scope.filteredsuperheroes = [];
angular.forEach(superheroes, function(superhero) {
var newEntry = {};
newEntry['text'] = superhero.name;
$scope.filteredsuperheroes.push(newEntry);
});
$scope.loadSuperheroes = function(query) {
return $http.get('/filteredsuperheroes?query=' + query);
};
Provide a live example, so I'll could test this :) I'm not sure that will work, but you should easily understand what I mean :)
The autocomplete's source attribute needs a promise, so if you want to use an already existing array of objects you'll have to return a promise that resolves to it:
$scope.superheroes = [{"id":1, "name":"Batman"}, {"id":2, "name":"Superman"}];
$scope.loadTags = function(query) {
var deferred = $q.defer();
deferred.resolve($scope.superheroes);
return deferred.promise;
};
and, as your displayed property name is not text (default by tagsInput), you need to specify it by adding the attribute display-property="name" to tags-input element:
<tags-input ng-model="superheroesModel" display-property="name" add-on-paste="true">
<auto-complete min-length="1" source="loadTags($query)"></auto-complete>
</tags-input>
I forked a simple autocomplete example from ngTagsInput Demo Page and made these changes. Check it out these changes here.

Categories