Dynamically update a select box depending on JSON data with AngularJS - javascript

I am quite new to AngularJS and have the following problem: I have two select boxes which I fill with data that is stored in an external JSON file. I want to dynamically fill the second box depending on the item that was selected in the first box. Every item in the first box has a key called relation. I want to use the value of this key as a trigger for dynamically updating the items available in the second box.
Can anyone help me on this? I have already tried to write a function but it doesn't work. Thanx in advance.
This is the JSON structure:
{
"filterElements": [
{
"parameters": [
{
"paraName": "paraOne",
"relation": "default"
},
{
"paraName": "paraTwo",
"relation": "default"
},
{
"paraName": "paraThree",
"relation": "defaultshort"
}
]
},
{
"relations": [
{
"defaultrelation":
[
"equals",
"does not equal",
"greater than",
"less than"
]
},
{
"defaultshort":
[
"equals",
"does not equal"
]
}
]
}
]
}
MyFiddle

Based on you're fiddle, you're missing to bootstrap application. Example:
<body ng-app="list">
...
</body>
After that, you need to register ListCtrl to the existing application.
var app = angular.module('list',[]);
app.controller('ListCtrl', ListCtrl);
function ListCtrl($scope, $http) {
...
}
After doing this, you're controller will be executed, you're request will be made and you can bind the data to your view.

I got it. Here is the solution if anyone is interested:
$scope.change = function (paraSelection) {
$scope.filteredrelations = [];
for(var key in $scope.relations){
if(angular.isDefined($scope.relations[key][paraSelection.relation])){
$scope.filteredrelations = $scope.relations[key] paraSelection.relation];
}
}
};
Complete working example can be found here:
Plunker

Related

Populating kendo-tree using from Json

I am in Angular environment using Kendo. All I want to do is following:
Take Json
Produce Kendo tree using it
I have tried it with simple data and it seems to work fine. But this time I have somewhat complex data and it seems like it does not work well with complex Json. I have been trying to have it render Json but it seems like it keeps on thinking and never comes back. I have created a sample Dojo for reference:
http://dojo.telerik.com/EdOqE
I am not sure what am I doing wrong but it just does not seem to work. Can anyone help me with this please?
I presume you have controll over the resultant json, because you'll have to change it a little to fit the TreeView's expected format. Check this out:
{
"items": [{ // Projects
"Id": 0,
"Name": "Your Example Project",
"CreatedOn": "",
"hasChildren": true,
"items": [{ // Analyses
"Id": 0,
"Name": "1.0 - Your Example Run",
"CreatedOn": "",
"hasChildren": true,
"items": [{ // Samples
"Id": 0,
"Name": "Sample 1",
"hasChildren": false,
"Description": "ample frample sample"
}, {
"Id": 0,
"Name": "Sample 2",
"hasChildren": false,
"Description": null
}]
}]
}]
};
The above json is what I did to work in the widget. First of all, the collection properties were renamed to items. All of them, in all levels. With that, kendo will know how property it should deal with. A hasChildren property was added to let it know when it has to show the expand icon. Otherwise it will show the expand option even if the item doesn't haves any children. So user clicks it and get an empty result.
This is the widget initialization options:
{
dataSource: new kendo.data.HierarchicalDataSource({
data: things,
schema: {
data: "items"
}
}),
dataTextField: "Name"
};
With schema.data I tell which property kendo will deal as the collection item. The dataSource expects an array, but if you give him an object, you have to set this property. If it was an array, then kendo would look for item property of each child for default. dataTextField is the name of the property it will use as the label.
Demo
Here is another demo with the data as an array. No need to set schema.data.
Update:
I was afraid you would say that. Yes, there is a way to deal with the data if you can't change it in the server-side. You have to intercept the data at the schema.parse() method and change the resultant data object property to items, so then the widget will understand:
schema: {
data: "items",
parse: function(data) {
if (data.hasOwnProperty("Projects")) {
return { items: data.Projects };
}
else if (data.hasOwnProperty("Analyses")) {
return { items: data.Analyses };
}
else if (data.hasOwnProperty("Samples")) {
return { items: data.Samples };
}
}
}
Demo
Every node when opened will call parse with items collection as data parameter. You have to return a new object with the property name as items instead of Projects, Analysis or Samples.
I forgot you can't touch the data, so can't add hasChildren property as well. Then you have to add a tiny logic into parse to set those properties in each level, otherwise the expand icon would not appear:
schema: {
data: "items",
parse: function(data) {
if (data.hasOwnProperty("Projects")) {
data.Projects.forEach(p => {
p.hasChildren = false;
if (p.hasOwnProperty("Analyses")) {
p.hasChildren = true;
}
});
return { items: data.Projects };
}
else if (data.hasOwnProperty("Analyses")) {
data.Analyses.forEach(a => {
a.hasChildren = false;
if (a.hasOwnProperty("Samples")) {
a.hasChildren = true;
}
});
return { items: data.Analyses };
}
else if (data.hasOwnProperty("Samples")) {
return { items: data.Samples };
}
}
}
Demo
It is ugly, I know. But get used to Kendo, it is the it goes with it.

Dynamically Load ng-options from API with Angular

I would like to dynamically load select elements from an API request.
Here is my controller:
var myApp = angular.module('myApp',[]).controller('tripCtrl', function($scope){
//Call to API to get people
$scope.people = [
{
"id": 1,
"name": "Joe Hamlet"
},
{
"id": 2,
"name": "Mary Jane"
},
{
"id": 3,
"name": "Tom Lee"
}
];
//Call to API to get the element to load
$scope.selectElement =
{
"Options": "person[dynamicValue] as person[dynamicDisplayName] for person in people",
"DisplayName": "name",
"Value": "id"
};
//Dynamicly load properties
$scope.dynamicValue = $scope.selectElement.DisplayName;
$scope.dynamicDisplayName = $scope.selectElement.Value;
});
HTML:
<select ng-model="selectedPerson" ng-options="{{selectElement.Options}}">
<option value="">Select</option>
</select>
{{selectedPerson}}
I created a JSFiddle trying to accomplish this. http://jsfiddle.net/HB7LU/9493/
I found this question which I was able to implement, but when I tried to set the ng-options from the Element's Options property, it failed to load. When inspected the HTML the code looks to be set properly, but the model binding isn't working.
Edit 12/28/2014:
After updating the Angular version in the original JS Fiddle, it worked properly, however when I expanded to use an actually API, I found another issue with loading ng-options dynamically. Here is the more in depth JS Fiddle: http://jsfiddle.net/zjFp4/330/
Also here is my updated controller. The dataService.getElement() calls a hard coded string, where as the dataService.getElementFromApi() calls the same exact string, just from json-generator (which is the mock API). When inspected the objects set from the API, everything is there, so it must be an issue with the binding in Angular. Any ideas on how to fix this?
function tripCtrl($scope, dataService) {
//Call to API to get people
dataService.getPeople().then(
function (event) {
$scope.people = event;
},
function (s) {
console.log(s); }
);
//Call to API to get the element to load
$scope.selectElement = dataService.getElement();
dataService.getElementFromApi().then(
function (event) {
$scope.apiElement = event;
$scope.dynamicValue = $scope.apiElement.Value;
$scope.dynamicDisplayName = $scope.apiElement.DisplayName;
},
function (s) {
console.log(s); }
);
}

AngularJS: How to create a model which holds an array for a dynamic list of input fields?

I have quite an interesting question (I hope) for all you AngularJS gurus out there. I am looking to create a dynamic list of form input fields based on a SELECT dropdown. As an example, we have a number of categories with each category having a set of specifications which are unique to that category. To help with the explanation we have the following:
Firstly, in the controller we start by initializing the models.
$scope.category = {};
$scope.category.specs = [];
Next we ready the data to be used in the form (actually retrieved from the server via $http). We also initialize a variable to the first element in the categories array.
$scope.categories = [
{ "id": "1", "name": "mobile", specs: [
{ "id": "1", "label": "Operating System" },
{ "id": "2", "label": "Camera type" } ] },
{ "id": "2", "name": "laptop", specs: [
{ "id": "1", "label": "Operating System" },
{ "id": "2", "label": "Graphics Card" } ] }
};
$scope.selectedCategory = $scope.categories[0];
In the form, we have a dropdown which when selected loads the appropriate input fields specific to that category. We use the ngRepeat directive to accomplish this. This is a dynamic list of fields based on $scope.categories.specs. (please note the ???)
<select ng-model="selectedCategory" ng-options="category.name for category in categories"></select>
<div ng-repeat="spec in selectedCategory.specs">
<label>{{spec.label}}</label>
<input type="text" ng-model="???">
</div>
Ultimately, when the user clicks the submit button, we would like to extract the category he/she has selected and then package it together with the specifications they have filled in. The post request should contain something like the following for instance (of course, I only included one spec item, but in reality there would be many):
{ "id": "1", specs [ { "id": "2", "details": "RADEON HD 8970M" } ] }
Unfortunately I am not really sure how to accomplish this. I need to somehow create an array for the spec model, and then ensure that both the ID and user entered data are appropriately extracted... what goes in the ??? and what do we do after? Any help would be much appreciated.
this is how I do it. I make a form, validate it with angular, and then when its valid I submit it with a function.
<form name="signup_form" novalidate ng-submit="signupForm()"></form>
$scope.signupForm = function() {
var data = $scope.signup;
$http({
method : 'POST',
url : 'http://yoursite.com/mail.php',
data : $.param(data), // pass in data as strings
headers : { 'Content-Type': 'application/x-www-form-urlencoded' } // set the headers so angular passing info as form data (not request payload)
})
.success(function(data) {
});
}
also if you want to look at another form validation system for angular check out http://nimbly.github.io/angular-formly/#!/ It may help you solve your current form system.
In the controller, initialize $scope.specDetails as follows:
$scope.specDetails = {};
angular.forEach($scope.categories, function (category, index1) {
$scope.specDetails[category.id] = {};
angular.forEach(category.specs, function (spec, index2) {
$scope.specDetails[category.id][spec.id] = '';
});
});
In the html, replace "???" with specDetails[selectedCategory.id][spec.id]

Angularjs ng-repeat not updating after array update

I'm not sure what I'm missing here but I'm trying to update a value inside an array, and then have this reflected in the repeater. Do I need to make a copy or something before applying the update in order for Angular to show the changes?
---sample json
"lists": [
{
"name": "one",
"enabled": true
},
{
"name": "two",
"enabled": false
}
]
!-- code
setTimeout(function(){
$scope.$apply(function(){
$scope.lists[1].enabled = true;
});
},1);
!--- html
<span data-ng-repeat="list in lists | filter: {enabled: true}"></span>
From the "other controller" you are talking about broadcast an event:
$rootScope.$broadcast('listChange', listArray);
Then in the controller that controls your $scope.lists value, listen for the event:
$scope.$on('listChange', function(event, list) {
$scope.$apply(function() {
// Update goes here
});
});
It might help if you use angulars built-in timeout function $timeout.
$timeout(function(){
$scope.lists[1].enabled = true;
},1);
Documentation here: https://docs.angularjs.org/api/ng/service/$timeout
Add your lists variable to the $scope inside your controller like this:
$scope.lists = [{
"name": "one",
"enabled": true
},
{
"name": "two",
"enabled": false
}];
You also have to add something inside the <span>, because the Html you posted would not display anything. (You need to do something inside the <span> tag in order to show something)
<span ng-repeat="list in lists | filter:{enabled: true}">{{list.name}}</span>
Now when you update the lists variable, this will be reflected in the Html immediately.
Works fine for me. Hope i could help!

Fetch the specific column value from Datatable when user clicks

I have a datatable populated with aaData which is depicting the task created by users. Now, there is an action column in datatable which has two or three action buttons or logos like pdf - to view the user guide of that task, browse- link for the source code of the task and one is contributors logo which onclick should display the contributors for that particular task.
The aaData is of the following format which is populating the table
"aaData": [
[
"JSAG Home Page",
"JSAG Home page contains information about various POCs done",
"05/12/2012",
[
{
"displayValue":"Browse",
"link":"http://myTask.com/home",
"displayIcon" : "browselogo"
},
{
"displayValue":"Source Code",
"link":"svn/HomePage/trunk/",
"displayIcon" : "svnlogo"
},
{
"displayValue":"Audience Overview",
"link":"svn/Documents/Audience Overview.pdf",
"displayIcon" : "pdflogo"
},
{
"displayValue":"Contributors: ABC,XYZ",
"link":"#",
"displayIcon" : "people"
}
],
],
[
"Backlog",
"Backlog Forum application is designed to provide a platform for different groups to maintain backlog task items. ",
"25/08/2012",
[
{
"displayValue":"Browse",
"link":"http://mytask.com/BacklogApp",
"displayIcon" : "browselogo"
},
{
"displayValue":"Source Code",
"link":"svn/trunk/webapp-project/",
"displayIcon" : "svnlogo"
},
{
"displayValue":"Contributors: ABC",
"link":"#",
"displayIcon" : "people"
}
],
]
]
This format is for all datatables and contributors logo is there in all. What i wanted was, when user clicks the contributors icon, he should be able to see those contributors "ABC, XYZ, PQR".
I thought of fetching the action column data and then $each() the contributors array but i am not able to proceed with it.
How can i achieve this thing? How can i pick up the column value onclick because each datatable is being populated dynamically.
Please help.
Below is the code to populate a contributors div
$(document).on('click', '#contributor', function(contributors){
$.each(contributors, function(i, data) {
var ul_data = "<li><h3>"+ data+ "</h3></li>";
$("#contributors_div").append(ul_data);
});
}
$('#contributors_div').show();
});
How do i getrecentActdata as my contributors JSON array
Its going to be similar to this, provided you are declaring you datatable in the variable oTable
$(document).on('click', '#contributor', function(){
var aPos = oTable.fnGetPosition( $(this) );
console.log(aPos);
//if aPos returns an array in console, use first val at pos zero to get row data
var aData = oTable.fnGetData(aPos[0]);
console.log(aData);
// inspect your returned object, then tailor your $.each iteration
$.each( aData["contributors"], function(i, data) {
var ul_data = "<li><h3>"+ data+ "</h3></li>";
$("#contributors_div").append(ul_data);
});
}
$('#contributors_div').show();
});

Categories