how to get formatted/require json array as per dynamic data - angularjs

I'm having two dropdowns(ddls). when page loads, first ddl gets loaded with data. User can make his choice in first ddl and according to that second ddl gets filled with source(happens dynamically every time).
below these dropdowns, there is add button. if user clicks add button again in new row two dropdowns come and same scenario is then applicable. more no of rows can be added by add buttons .
beside two ddls, there is one remove buttons by pressing which particular row can be deleted.
No question is how can i get desire json array in specific format as described below.
i want json array like this....
$scope.project=[{
securityId: "first Dropdown selected value" ,
contactId:"second Dropdown selected value"
}]
(if there is only one row)
for 2 rows, I want length size 2 of $scope.project with desire and appropriate values.
for nth rows, the length of $scope.project should be n with appropriate values....
Once have a look at already made fiddle, you will come to know more. please check your browser console. I'm getting $scope.project array but not in required format.
It could be very easy for angular lovers. I don't know why i'm not getting the solution.
http://jsfiddle.net/micronyks/ZwwH7/6/
html
<html ng-app>
<div ng-controller="ctrl">
<div ng-repeat="additional in additionals">
<select ng-model="additional.securityId" ng-change="selectRoles(additional.securityId,additional)" ng-options="w.securityId as w.securityRoleName for w in SecurityRoles"></select>
<select ng-model="additional.personId" ng-change="selectperson(additional.personId,additional)" ng-options="w.personId as w.personName for w in additional.Personsddl"></select>
<button ng-click="remove($index)">remove</button>
</div>
<button ng-click="add()">add row</button>
</div>
</html>
.js file...
function ctrl($scope) {
$scope.additionals=[{}];
$scope.project=[{}];
$scope.SecurityRoles = [{
securityId: 1,
securityRoleName: "SuperAdmin"
}, {
securityId: 2,
securityRoleName: "Admin"
}
, {
securityId: 3,
securityRoleName: "Guest"
}];
$scope.Persons = [{
personId: 1,
contactId:1,
personName: "john"
}, {
personId: 2,
contactId:1,
personName: "jack"
},{ personId: 3,
contactId:2,
personName: "Johnson"
},{ personId: 4,
contactId:2,
personName: "rock"
},
{ personId: 5,
contactId:3,
personName: "bank"
}];
$scope.selectRoles=function(id,additional)
{
additional.Personsddl=[];
angular.forEach($scope.Persons,function(record){
if(record.contactId==id)
{
additional.Personsddl.push(record);
}
});
$scope.project.push({roleId:id});
}
$scope.add=function()
{
$scope.additionals.push({});
}
$scope.remove=function($index){
$scope.additionals.splice($index,1);
}
$scope.selectperson=function(id)
{
$scope.project.push({contactId:id});
console.log($scope.project);
}
}

please see here: http://jsfiddle.net/9pqjN/
HTML:
<html ng-app>
<div ng-controller="ctrl">
<p>Project :</p> <pre>{{project |json}}</pre>
<div ng-repeat="user in project">
<select ng-model="user.securityId" ng-options="w.securityId as w.securityRoleName for w in SecurityRoles"></select>
<select ng-model="user.personId" ng-options="w.personId as w.personName for w in Persons"></select>
<button ng-click="remove($index)">remove</button>
</div>
<button ng-click="add()">add row</button>
</div>
</html>
js:
function ctrl($scope) {
$scope.additionals = [];
$scope.project = [];
$scope.SecurityRoles = [{
securityId: 1,
securityRoleName: "SuperAdmin"
}, {
securityId: 2,
securityRoleName: "Admin"
}, {
securityId: 3,
securityRoleName: "Guest"
}];
$scope.Persons = [{
personId: 1,
contactId: 1,
personName: "john"
}, {
personId: 2,
contactId: 1,
personName: "jack"
}, {
personId: 3,
contactId: 2,
personName: "Johnson"
}, {
personId: 4,
contactId: 2,
personName: "rock"
}, {
personId: 5,
contactId: 3,
personName: "bank"
}];
$scope.add = function () {
$scope.project.push({});
}
$scope.remove = function ($index) {
$scope.project.splice($index, 1);
}
}

sylwester has it almost. Added a filter in my case:
<select ng-model="additional.personId"
ng-options="w.personId as w.personName for w in Persons | filter:{contactId: additional.securityId}">
</select>
Here is the complete demo http://jsfiddle.net/9DcXA/1/
Also note, there is no point in having securityId as well as contactId in output json because I see you are filtering the second drop down based on the securityId matching with contactId of Persons. I suppose you meant to show securityId and personId in result.

Related

Display angularjs-dropdown-multiselect inline along with drop down label name

I am using angularjs-dropdown-multiselect .
code sample:
PLatform : <div ng-dropdown-multiselect="" options="example13data" selected-model="example13model" extra-settings="example13settings"></div>
JS:
$scope.example13model = [];
$scope.example13data = [ {id: 1, label: "David"},
{id: 2, label: "Jhon"},
{id: 3, label: "Lisa"},
{id: 4, label: "Nicole"},
{id: 5, label: "Danny"} ];
$scope.example13settings = { smartButtonMaxItems: 3, smartButtonTextConverter: function(itemText, originalItem) {
if (itemText === 'Jhon') { return 'Jhonny!'; }
return itemText; } };
reference : http://dotansimha.github.io/angularjs-dropdown-multiselect/docs/#/main
I want to display label name and dropdown in a single line as below.
But after using multi select api i am unable to display then inline, it displays as below, please let me know how to resolve this.
I found that putting it in a span instead of a div solves the problem.
Try this instead:
Platform
<span
ng-dropdown-multiselect=""
options="example13data"
selected-model="example13model"
extra-settings="example13settings">
</span>

Angular how to have multiple selected

I have this array of objects. that holds somethings like this.
[
{
id: 1,
name: "Extra Cheese"
},
{
id: 2,
name: "No Cheese"
}
]
im iterating thru the array here
<select ng-model="item.modifiers" multiple chosen class="chosen-select" tabindex="4" ng-options="modifier._id as modifier.name for modifier in modifiers"></select>
The thing item.modifiers model that has an array of this 2 id
[
1,2
]
I want the multi select to auto selected the two ids that are in the item.model
I want the final result to look something like this
Your code is pretty much working already, maybe some of the variables are not assigned correctly (eg. id instead of _id)
angular.module('test', []).controller('Test', Test);
function Test($scope) {
$scope.modifiers = [
{
id: 1,
name: "Extra Cheese"
},
{
id: 2,
name: "No Cheese"
}
]
$scope.item = {};
// add this for pre-selecting both options
$scope.item.modifiers = [1,2];
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-app='test' ng-controller='Test'>
<select ng-model="item.modifiers" multiple chosen class="chosen-select" tabindex="4" ng-options="modifier.id as modifier.name for modifier in modifiers"></select>
</div>
If I understand the question correctly, you're wanting to pre-select the two options.
To do this you will need to set your ng-model to point to the actual objects you are iterating over.
You will also need to change your ng-options to ng-options="modifier as modifier.name for modifier in modifiers" rather than just iterating over the ids.
Here's the relevant documentation under Complex Models (objects or collections)
https://docs.angularjs.org/api/ng/directive/ngOptions
Something like this should work:
HTML:
<select ng-model="$ctrl.item.modifiers"
ng-options="modifier as modifier.name for modifier in $ctrl.modifiers"
multiple chosen class="chosen-select" tabindex="4" >
</select>
JS:
app.controller("my-controller", function() {
var $ctrl = this;
$ctrl.modifiers = [{
id: 1,
name: "Extra Cheese"
}, {
id: 2,
name: "No Cheese"
}];
$ctrl.item = {
modifiers: []
}
$ctrl.$onInit = function() {
const id1 = 1;
const id2 = 2;
for (const modifier of $ctrl.modifiers) {
if (modifier.id === id1 || modifier.id === id2) {
$ctrl.item.modifiers.push(modifier);
}
}
}
}
Here's a pen showing the result:
http://codepen.io/Lahikainen/pen/WooaEx
I hope this helps...

Angularjs push list elements to an array

It's a small memory game: the player has to remember a list of words and then he is presented with another list which contains few words from the original list where he has to decide if any of these words were present in the original list. For that he can click on 'Yes' or 'No' radio button.
<div align="center" ng-show="showWords" style="margin-bottom:1cm;">
<div ng-repeat="word in words">
<h4>{{word}}</h4>
</div>
</div>
<div align="center" ng-show="showTest" style="margin-bottom:1cm;">
<div ng-repeat="word in wordsPresent | limitTo:limitTo">
<h4>{{word}}</h4>
<label>
<input type="radio" value="yes">
Yes
</label><br/>
<label>
<input type="radio" ng-value="no">
No
</label><br/>
</div>
</div>
...
<div align="center" ng-if="showOk">
<button class="button button-dark" ng-click="pushToArray()">OK</button>
</div>
In my controller I have:
$scope.words=['Okra', 'Musa', 'Sky', 'India', 'Rose', 'Titanic', 'Onion', 'Germany', 'Beer', 'Run', 'Garden', 'Mountain']
$scope.wordsPresent=['King', 'Garden', 'America', 'Sky', 'Potato', 'Germany', 'Rose', 'Whisky', 'Mumbai', 'Walk']
$scope.playerChoices=[]
The first array is the original array against which I have to check, second array is what I am presenting to the user right now, and third array might be the array where I push his choices.
It looks like following:
How can I implement this?
Update
Please see this updated plunker demo.
To populate the data dynamically onto the DOM, you can use ng-repeat. Please see the code on plunker.
<span ng-repeat="item in someArray">{{item}}</span>
To interpolate the looped item, use {{ }}.
Important : Just please avoid duplicate data on $scope.wordsPresent array coz it will produce error on ng-repeat.
Instead of pushing the "choices" at the end of the quiz/survey(?) why not push it every time the radio changes it's value? Push to array if yes is selected and remove from array if no is selected.
In that case you can use ng-change event to trigger the pushing and removing of data in the array, on the controller. You should take advantage of the 2 way data binding angularjs is offering.
You can then cross check your arrays.
Please see this plunker demo I created and I hope it will help you.
If you can make do with a library, I would suggest lodash.
_.intersection([2, 1], [2, 3]);
// ➜ [2]
Or in the context of your problem:
_.intersection($scope.words, [$scope.wordsPresent]);
// ➜ ['Sky', 'Germany', 'Rose', 'Garden']
https://lodash.com/docs#intersection
It seems to me if you want to check for correct answers, you need to do more than just compare arrays. Suppose they select "No" when something is actually in the list. First, I would put a key field on the items in my array so you are not so limited. Here is a working Plunker
Your data should probably look something like this:
$scope.words = [{
id: 11,
name: 'Okra'
}, {
id: 12,
name: 'Musa'
}, {
id: 4,
name: 'Sky'
}, {
id: 13,
name: 'India'
}, {
id: 14,
name: 'Rose'
}, {
id: 15,
name: 'Titanic'
}, {
id: 16,
name: 'Onion'
}, {
id: 6,
name: 'Germany'
}, {
id: 17,
name: 'Beer'
}, {
id: 18,
name: 'Run'
}, {
id: 2,
name: 'Garden'
}, {
id: 19,
name: 'Mountain'
}]
$scope.wordsPresent = [{
id: 1,
name:'King'
},
{
id: 2,
name: 'Garden'
}, {
id: 3,
name: 'America'
}, {
id: 4,
name: 'Sky'
}, {
id: 5,
name: 'Potato'
}, {
id: 6,
name: 'Germany'
}, {
id: 7,
name: 'Rose'
}, {
id: 8,
name: 'Whisky'
}, {
id: 9,
name: 'Mumbai'
}, {
id: 10,
name: 'Walk'
}]
Then I would add an answer field (you could include it when you set up your data or you can include i after like this:
setAnswers();
function setAnswers() {
angular.forEach($scope.wordsPresent, function (value, key) {
$scope.wordsPresent[key].answer = 'no';
});
angular.forEach($scope.words, function (value, key) {
$scope.words[key].answer = 'yes';
})
}
Your HTML could look like this:
<div ng-app="myModule" ng-controller="HomeCtrl">
<div align="center" style="margin-bottom:1cm;">
<div ng-repeat="word in wordsPresent | limitTo:limitTo">
<h4>{{word.name}}</h4>
<input type="radio" ng-model="word.answer" value="yes">
Yes
<br />
<input type="radio" ng-model="word.answer" value="no">
No
<br />
</div>
</div>
<div ng-show="showAnswers">
<span>Correct Answers: {{correct}}</span> <span>Incorrect Answers: {{wrong}}</span>
You selected:
<div ng-repeat="a in playerChoices">
<span>{{a.name}}</span> <span>{{a.answer}}</span>
</div>
</div>
<div align="center">
<button class="button button-dark" ng-click="pushToArray()">OK</button>
</div>
</div>
And in your controller:
$scope.pushToArray = function () {
$scope.correct = 0;
for (var i = 0; i < $scope.wordsPresent.length; i++) {
$scope.playerChoices.push($scope.wordsPresent[i]);
}
$scope.showAnswers = true;
$scope.correct = correctAnswers($scope.playerChoices, $scope.words);
}
function correctAnswers(checkerArray, targetArray) {
correct = 0;
wrong = 0;
for (var i = 0; i < checkerArray.length; i++) {
if (checkerArray[i].answer == 'yes') {
if (containsObject(checkerArray[i], targetArray) == true) {
correct = correct + 1;
}
}
else if (checkerArray[i].answer = 'no') {
if (containsObject(checkerArray[i], targetArray) == false) {
correct = correct + 1;
}
}
}
return correct;
}
function containsObject(obj, list) {
var i;
for (i = 0; i < list.length; i++) {
if (list[i].id === obj.id) {
return true;
}
}
return false;
}
Happy coding!

AngularJS filter object by property on tree structure

I am posting this because I never found a precise answer for filtering nested objects (tree sturcture).
Let's say we have an JSON tree structure that looks like this:
$scope.tree = [{
id: 1,
parent_id: 0,
name: 'Root Item',
items: [
{
id: 2,
parent_id: 1,
name: '1st Child of 1'
},
{
id: 3,
parent_id: 1,
name: '2nd Child of 1'
},
{
id: 4,
parent_id: 1,
name: '3rd Child of 1',
items:[
{
id:5,
parent_id: 4,
name:'1st Child of 5'
},
{
id:6,
parent_id: 4,
name:'2nd Child of 5'
}
]}
]
}]
How do we traverse the tree with a filter to get object with id 6 for example?
If we use the following filter for example:
<div data-ng-init="selectedItem = (tree | filter:{id:6})">
<h1>The name of item with id:6 is selectedItem.name</h1>
</div>
It will only iterate through the first level in which will only find id:1.
So, in order to get nested level objects we must use a recursive filter like this one:
angular.module("myApp",[])
.filter("filterTree",function(){
return function(items,id){
var filtered = [];
var recursiveFilter = function(items,id){
angular.forEach(items,function(item){
if(item.id === id){
filtered.push(item);
}
if(angular.isArray(item.items) && item.items.length > 0){
recursiveFilter(item.items,id);
}
});
};
recursiveFilter(items,id);
return filtered;
};
});
});
So, to use this filter in the markup you would call it like this:
<div data-ng-init="selectedItem = (tree | filterTree:6)">
<h1>The name of item with id:6 is selectedItem.name</h1>
</div>
Hope you find this useful, it took me some time to digest recursive filters.
Of course, this filter works to get 1 item since it returns [0] first object of filtered array. But if you want it to return more than 1 result you'll have to remove only that [0] at the return function and then use ng-repeat to iterate over filtered resutls.

Angularjs OrderBy on ng-repeat doesn't work

I'm trying to use AngularJS for my first project (a tournaments manager) and the orderBy filter on ng-repeat doesn't work :( I have read all the documentation about that, but nothing to do :/
So, I have vars defined on $scope like that :
$scope.order_item = "count_win";
$scope.order_reverse = false;
$scope.teams = {
100 : {
id: 100,
name: "XXX",
count_win: 1,
count_loose: 2,
goal_average: 1,
},
200 : {
id: 200,
name: "XXX",
count_win: 1,
count_loose: 2,
goal_average: 1,
},
[...]
};
Now, on my view i'm trying to reorder (first with only one order item) but never work...
<tr ng-repeat="team in teams | orderBy:order_item:order_reverse">
<td>{{team.name}}</td>
<td>{{team.count_loose}}</td>
<td>{{team.goal_average}}</td>
</tr>
The second time, I want to reorder from 2 pieces of information: count_win and goal_average if first are equal.. I try to replace $scope.order_item like that, but if with one the code doesn't work, he'll never work with 2...
$scope.order_item = ['count_win','goal_average'];
Thank you all for reading and sorry for the post size.
$scope.teams isn't an array (it's an object of objects), and the orderBy filter only works with arrays. If you make $scope.teams an array, it will work:
$scope.teams = [
{
id: 100,
name: "team1",
count_win: 3,
count_loose: 2,
goal_average: 2,
},
{
id: 200,
name: "team2",
count_win: 3,
count_loose: 2,
goal_average: 1,
},
{
id: 300,
name: "team3",
count_win: 1,
count_loose: 2,
goal_average: 1,
}
];
Or, you can add a special filter that works on objects, like this (borrowed from here):
app.filter('orderObjectBy', function() {
return function(items, field, reverse) {
var filtered = [];
angular.forEach(items, function(item) {
filtered.push(item);
});
filtered.sort(function (a, b) {
return (a[field] > b[field] ? 1 : -1);
});
if(reverse) filtered.reverse();
return filtered;
};
});
And use it like this:
<tr ng-repeat="team in teams | orderObjectBy:order_item:order_reverse">
Note that this custom filter will not work with an array of sort orders as in the second part of your question.
You don't have to create a scope parameter for your orderBy, you can directly do this in your markup if you are dealing with arrays.
<tr ng-repeat="team in teams | orderBy:count_win:false">
With two parameters, you should just do
<tr ng-repeat="team in teams | orderBy:['count_win','goal_average']">
After for a more complex order, you could create a function in your scope like so :
$scope.customOrder = function (team) {
//custom
}
And just call it like
<tr ng-repeat="team in teams | orderBy:customOrder">
Like #Jerrad said, ng-repeat only works with arrays, so you need to convert your teams object into an array to get it work properly.
ng-repeat works only on arrays, not on JSON objects.
This was already discussed here: Angular - Can't make ng-repeat orderBy work
You either have to change the JSON object to an Array, or to convert it on the fly.
The controller could then look like this:
var app = angular.module('app', []);
app.controller('Ctrl', function ($scope) {
$scope.teams = [
{
id: 100,
name: "A Team",
count_win: 1,
count_loose: 2,
goal_average: 1
},
{
id: 200,
name: "C Team",
count_win: 2,
count_loose: 3,
goal_average: 4
},
{
id: 300,
name: "B Team",
count_win: 4,
count_loose: 1,
goal_average: 8
}
];
$scope.predicate = 'name';
});
I created a fiddle here with a demo containing your data:
http://jsfiddle.net/c3VVL/

Resources