How to extract data from json using angularjs? - angularjs

Here in {{msg}} I can display all jason data with Selected:true or false..
but What I need is I don't want to display all the datas, when I click Save button I want to display questions.id,option.id and selected:true or false below the textbox
we will get all the json data from $scope.questions.
Home.html
<div ng-repeat="question in filteredQuestions">
<div class="label label-warning">Question {{currentPage}} of {{totalItems}}.</div>
<div class="row">
<div class="row">
<h3>{{currentPage}}. <span ng-bind-html="question.Name"></span></h3>
</div>
</div>
<div class="row text-left options">
<div class="col-md-6" ng-repeat="option in question.Options" style="float:right;">
<div class="option">
<label class="" for="{{option.Id}}">
<h4> <input id="{{option.Id}}" type="checkbox" ng-model="option.Selected" ng-change="onSelect(question, option);" />
{{option.Name}}</h4>
</label>
</div>
</div>
</div>
<div class="center"><button ng-click="save()">Save</button></div>
<div class="center"><textarea rows="5" cols="50">{{msg}}</textarea></div>
</div>
controllers.js
var HomeController = function ($scope, $http, helper) {
/*$scope.names = response.data;
$scope.detectChange=function(){
$scope.msg = 'Data sent: '+ JSON.stringify($scope.filteredQuestions);
}*/
$scope.save = function() {
$scope.msg = 'Data sent: '+ JSON.stringify($scope.questions);
}
$scope.quizName = 'data/csharp.js';
$scope.loadQuiz = function (file) {
$http.get(file)
.then(function (res) {
$scope.quiz = res.data.quiz;
$scope.config = helper.extend({}, $scope.defaultConfig, res.data.config);
$scope.questions = $scope.config.shuffleQuestions ? helper.shuffle(res.data.questions) : res.data.questions;
$scope.totalItems = $scope.questions.length;
$scope.itemsPerPage = $scope.config.pageSize;
$scope.currentPage = 1;
$scope.mode = 'quiz';
$scope.$watch('currentPage + itemsPerPage', function () {
var begin = (($scope.currentPage - 1) * $scope.itemsPerPage),
end = begin + $scope.itemsPerPage;
$scope.filteredQuestions = $scope.questions.slice(begin, end);
});
});
}
$scope.loadQuiz($scope.quizName);
}
HomeController.$inject = ['$scope', '$http', 'helperService'];
csharp.js
{
"quiz": {
"Id": 2,
"name": "C# and .Net Framework",
"description": "C# and .Net Quiz (contains C#, .Net Framework, Linq, etc.)",
"paragraph": "In 2015 Microsoft released ASP.NET 5.ASP.NET 5 is a significant redesign of ASP.NET.ASP.NET, MVC, and Web Pages are now merged into a single framework named MVC 6.It includes the following features:Linux support OSX support Node.js supportA ngularJS supportTag ,HelpersView, ComponentsWeb ,APIGruntJS ,supportBower, supportNo ,Visual BasicNo Web Forms"
},
"config": {
"shuffleQuestions": true,
"showPager": false,
"allowBack": true,
"autoMove": false
},
"questions": [{
"Id": 1010,
"Name": "Which of the following assemblies can be stored in Global Assembly Cache?",
"QuestionTypeId": 1,
"Options": [{
"Id": 1055,
"QuestionId": 1010,
"Name": "Private Assemblies"
}, {
"Id": 1056,
"QuestionId": 1010,
"Name": "Friend Assemblies"
}, {
"Id": 1057,
"QuestionId": 1010,
"Name": "Public Assemblies"
}, {
"Id": 1058,
"QuestionId": 1010,
"Name": "Shared Assemblies"
}]
}, {
"Id": 1019,
"Name": "Which of the following does NOT represent Integer?",
"QuestionTypeId": 1,
"Options": [{
"Id": 1055,
"QuestionId": 1010,
"Name": "Char"
}, {
"Id": 1056,
"QuestionId": 1010,
"Name": "Byte"
}, {
"Id": 1057,
"QuestionId": 1010,
"Name": "Short"
}, {
"Id": 1058,
"QuestionId": 1010,
"Name": "Long"
}]
}]
}
This is my answer of above code..here Displaying all the data
Data sent: [{"Id":1013,"Name":"Which of the following is NOT an Arithmetic operator in C#.NET?","QuestionTypeId":1,"Options":[{"Id":1055,"QuestionId":1010,"Name":"** (Double Star)","$$hashKey":"00X","Selected":false},{"Id":1057,"QuestionId":1010,"Name":"+ (Plus)","$$hashKey":"00Y","Selected":false},
"$$hashKey":"00C"}]
but I want to display the all the question id's and corresponding option id's and if it is selected,selected:true otherwise false in the format of above output

If you want to change what is presented to the user after saving you should change this function:
$scope.save = function() {
$scope.msg = 'Data sent: '+ JSON.stringify($scope.questions);
}
to something like:
$scope.save = function() {
$scope.msg = 'Question IDs:';
$scope.questions.forEach(function(el){
$scope.msg += el.Id + ',';
}
}
This for example will join all the ids of the array that conains all the questions.
To add options and selections you have to ng-model the value to some variable that you will use inside your controller.
I think you should check a little guide to angularjs two-way data binding

Related

Dynamic form using AngularJS, multiple values binding

I am looking for a best approach to convert a static form to an angular dynamic form. I am not sure how to bind multiple values to the same answer.
The static page is available at: https://jsfiddle.net/hvuq5h46/
<div ng-repeat="i in items">
<select ng-model="i.answer" ng-options="o.id as o.title for o in i.answersAvailable" ng-visible="y.TYPE = 'SINGLE'"></select>
<input type="checkbox" ng-model="i.answer" ng-visible="y.TYPE = 'MULTIPLE'" />
</div>
The JSON file
[
{
"id": 1,
"title": "Are you a student?",
"type": "SINGLE",
"answersAvailable": [
{
"id": 1,
"title": "Yes"
},
{
"id": 2,
"title": "No"
}
],
"answer": [
1
]
},
{
"id": 2,
"title": "Would you like to be an astronaut?",
"type": "SINGLE",
"answersAvailable": [
{
"id": 4,
"title": "Yes"
},
{
"id": 5,
"title": "No"
},
{
"id": 6,
"title": "I am not sure"
}
],
"answer": [
4
]
},
{
"id": 3,
"title": "What is your favourite planet?",
"type": "MULTIPLE",
"answersAvailable": [
{
"id": 7,
"title": "Earth"
},
{
"id": 8,
"title": "Mars"
},
{
"id": 9,
"title": "Jupiter"
}
],
"answer": [
7,
8
]
}
]
Things would be much simpler if you can use a multiple select, but I understand it might be difficult for user to interact (consider something like md-select, which transforms multiple select into a list of checkbox for you)
Multiple select:
<select multiple
ng-model="i.answer"
ng-options="o.id as o.title for o in i.answersAvailable"
ng-if="i.type == 'MULTIPLE'"></select>
Anyway it is completely ok to use HTML checkbox. To do that we would need to bind checkbox model into the data as usual, and then update the answer array simultaneously.
ng-model="o.selected"
ng-change="updateAnswer(i)"
Also, we'll need to copy existing data to model during init.
ng-init="initMultiple(i)"
Working code:
angular.module('test', []).controller('Test', Test);
function Test($scope) {
$scope.items = [{
"id": 1,
"title": "Are you a student?",
"type": "SINGLE",
"answersAvailable": [{
"id": 1,
"title": "Yes"
},
{
"id": 2,
"title": "No"
}
],
"answer": [
1
]
},
{
"id": 2,
"title": "Would you like to be an astronaut?",
"type": "SINGLE",
"answersAvailable": [{
"id": 4,
"title": "Yes"
},
{
"id": 5,
"title": "No"
},
{
"id": 6,
"title": "I am not sure"
}
],
"answer": [
4
]
},
{
"id": 3,
"title": "What is your favourite planet?",
"type": "MULTIPLE",
"answersAvailable": [{
"id": 7,
"title": "Earth"
},
{
"id": 8,
"title": "Mars"
},
{
"id": 9,
"title": "Jupiter"
}
],
"answer": [
7,
8
]
}
]
$scope.initMultiple = function(item) {
item.answersAvailable.forEach(function(option) {
option.selected = item.answer.indexOf(option.id) != -1;
});
}
$scope.updateAnswer = function(item) {
item.answer = item.answersAvailable.filter(function(option) {
return option.selected;
})
.map(function(option) {
return option.id;
});
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-app='test' ng-controller='Test'>
<div ng-repeat="i in items">
<select ng-model="i.answer[0]"
ng-options="o.id as o.title for o in i.answersAvailable"
ng-if="i.type == 'SINGLE'"></select>
<label ng-repeat="o in i.answersAvailable"
ng-if="i.type == 'MULTIPLE'"
ng-init="initMultiple(i)">
<input type="checkbox"
ng-model="o.selected"
ng-change="updateAnswer(i)" /> {{o.title}}
</label>
<div>{{i.answer}}</div>
</div>
</div>
Based on my experience, I will make a separation as two Angular models (or usually called services) for the form questions and another one which will collect the answers and eventually will be passed to the backend for further processing. This will provide me a flexibility to maintain both logic and presentation.
var myModule = angular.module('myModule', []);
myModule.factory('QuestionsFormService', function() {
var _question1;
var _question2;
var _question3;
function init(data){
//questions initiation
}
return init;
});
var myModule = angular.module('myModule', []);
myModule.factory('FormDataService', function() {
var _dataAnswer = {}
function init(){
//data initialization
}
function insertData(key, value){
_dataAnswer[key] = value
}
return init;
});
From the example of service models above, you need to make these available to your presentation through the Angular controller with Dependency Injection.
myModule.controller("MyCtrl", function($scope, FormDataService, QuestionsFormService) {
$scope.form_questions = QuestionsFormService.init();
$scope.form_answers = FormDataService.init()
//further logic to make these available on your view on your convenience
});
What you write on the HTML page as an Angular view is already close enough. You only need to change the binding to two models as I propose above. Thank you.

AngularJS Filed nested array of objects with array of objects

I'm trying to filter a nested array of objects with my own objects, by idSubject. But I'm not getting the right result.
I have articles (which have subjects)
And a array of objects (which are the subjects I want to filter the articles with)
Data looks like this:
So I'm trying to filter the array of articles by its subjects.
I tried the following:
<div class="panel panel-default"
ng-repeat="searchArticle in searchArticles | filter: {subjects: filterSubjects} as articleSearchResult">
So filterSubjects is the second screenshot and SearchArticles is the first screenshot.
Without much luck.
Hope you can help, please tell me if things are still unclear.
This custom filter will help you.
Example : http://plnkr.co/edit/jMizCLxPH6DtDA5wL15Q?p=preview
HTML:
<body ng-app="myApp">
<div ng-controller="MainCtrl">
<h2>Select Subjects</h2>
<div ng-repeat="subject in subjects">
<label>
<input type="checkbox" ng-model="filterSubjects[subject.id]" ng-true-value="'{{subject.id}}'" ng-false-value="''">{{subject.name}}</label>
</div>
<h2>Filtered Articles</h2>
<div ng-repeat="searchArticle in searchArticles | subjectFilter:filterSubjects">{{searchArticle.name}}</div>
</div>
</body>
JS:
var app = angular.module('myApp', []);
app.controller('MainCtrl', function($scope) {
$scope.searchArticles = [{
"name": "Article1",
"sid": "1"
}, {
"name": "Article2",
"sid": "1"
}, {
"name": "Article3",
"sid": "2"
}];
$scope.subjects = [{
"name": "Subject1",
"id": "1"
}, {
"name": "Subject2",
"id": "2"
}];
$scope.filterSubjects = [];
});
app.filter('subjectFilter', function() {
return function(articles, filterSubjects) {
filtered = articles.filter(function(e){return filterSubjects.indexOf(e.sid) >= 0},filterSubjects);
return filtered;
}
});
if you want to filter based on object :
var app = angular.module('myApp', []);
app.controller('MainCtrl', function($scope) {
$scope.searchArticles = [{
"name": "Article1",
"sid": "1"
}, {
"name": "Article2",
"sid": "1"
}, {
"name": "Article3",
"sid": "2"
}];
$scope.subjects = [{
"name": "Subject1",
"id": "1"
}, {
"name": "Subject2",
"id": "2"
}];
$scope.filterSubjects = [{
"name": "Subject1",
"id": "1"
}, {
"name": "Subject1",
"id": "2"
}];
});
app.filter('subjectFilter', function() {
return function(articles, filterSubjects) {
var sFiltered = [];
for (var i = 0; i < filterSubjects.length; i++) {
sFiltered.push(filterSubjects[i].id);
}
var filtered = articles.filter(function(e) {
return sFiltered.indexOf(e.sid) >= 0;
}, sFiltered);
return filtered;
}
});

Reading nested json in Angularjs

I am newbie to AngularJS. I have JSON file which I have to fetch using angularjs!
JSON File
{
"records": [
{
"students": [
{
"id": 1,
"name": "Bill",
},
{
"id": 2,
"name": "Steve",
}
],
"exstudent": [
{
"id": 1,
"name": "Woz",
},
{
"id": 2,
"name": "Jonathan",
}
]
}
]
}
Controller part snippet -
$http.get('json/somedata.json').success(function (data){
$scope.name = data.records.student.name;
$scope.exname = data.records.exstudent.name;
});
}])
HTML
<div class="panel-body" ng-repeat = "browse in name">
{{browse.student.name}}
</div>
Which part I am doing wrong? I think the problem is with ng-repeat!
Need Help
You can't use data.records.students.name as students is an Array.
You can however store its data into your $scope and use it in the ng-repeat:
$http.get('json/config.json').success(function (data){
$scope.students = data.records.students;
$scope.exstudents = data.records.exstudent;
});
Then in your HTML use the ng-repeat like this:
<div class="panel-body" ng-repeat="student in students">
{{student.name}}
</div>

How fill dropdown menu

I´m working with bootstrap and angularjs for the user interface and google appengine with java as a backend.
Just now I have a problem filling a dropdown menu, I see an empty list so I suspect that the problem is in the html code.
Front end:
<div class="dropdown" >
<select id="mySelPartido" class="form-control">
<option ng-repeat="partido in data.locations.partidos"
ng-selected="partido.selected" ng-model="partido.partido">{{partido.partido}}</option>
</select>
</div>
js in angular code (I debug this code and it works!):
$scope.status = 'loading...';
$scope.partido = "Select partidos";
$scope.data = {
"locations": {}
};
$http.get('https://myservice.appspot.com/_ah/api/partidoendpoint/v1/partido')
.then(function (res) {
$scope.data.locations.partidos = res.data.items;
$scope.status = "loaded "
+ $scope.data.locations.partidos.length
+ " partidos.";
});
My service response from app engine backend:
{
"items": [
{
"id": {
"kind": "Partido",
"appId": "s~myservice",
"id": "5066549580791808",
"parent": {
"kind": "Provincia",
"appId": "s~myservice",
"id": "5086253011697664",
"complete": true
},
"complete": true
},
"name": "Florencio Varela",
"kind": "partidoendpoint#resourcesItem"
},
{
"id": {
"kind": "Partido",
"appId": "s~myservice",
"id": "5094432508477440",
"parent": {
"kind": "Provincia",
"appId": "s~myservice",
"id": "5086253011697664",
"complete": true
},
"complete": true
},
"name": "La Matanza",
"kind": "partidoendpoint#resourcesItem"
}
],
"kind": "partidoendpoint#resources",
"etag": "\"PQS12KaO4-dKVfv_BcCoEkbIN9g/GvZKzZUnrHEP8TKWybTkd_fJbnc\""
}
Check the angular documentation for select.
Maybe try use the ngOptions directive in the select element. Example :
function demo($scope) {
$scope.items = [
{ name: 'foo' },
{ name: 'bar' },
{ name: 'baz' }
];
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app ng-controller="demo">
<select ng-options="item.name for item in items"
ng-model="selected">
</select>
<p>You have selected : {{ selected }}
</div>

Bind scope property to tab title

I am new to angularJS and I am having trouble with binding properties of scope so two way binding can work properly. I am using sample code to generate tabs.
<div ng-app="SampleApp">
<div id="tabs" ng-controller="GridController as gridcon">
<ul>
<li ng-repeat="tab in tabs"
ng-class="{active:isActiveTab(tab.url)}"
ng-click="onClickTab(tab)">{{tab.title}}</li>
</ul>
<div id="mainView">
<div ng-include="currentTab"></div>
</div>
<input type="button" ng-click="changedata()" value="Check" />
</div>
</div>
Now my scope have two observable arrays and I want to show count of those arrays in tab title. I am using following code for controller.
var appRoot = angular.module('SampleApp', ["kendo.directives"]);
appRoot.controller('GridController', ['$scope', function ($scope) {
$scope.data1 = new kendo.data.ObservableArray([
{
issueId: 1,
issue: "County Incorrect"
},
{
issueId: 2,
issue: "City Incorrect"
},
{
issueId: 3,
issue: "Name Incorrect"
}
]);
$scope.data2 = new kendo.data.ObservableArray([
{
"id": 11,
"first_name": "James",
"last_name": "Butt",
"company_name": "Benton, John B Jr",
"address": "6649 N Blue Gum St",
"city": "New Orleans",
"county": "Bridgepoort",
"state": "LA",
"zip": 70116,
"phone1": "504-621-8927",
"phone2": "504-845-1427",
"email": "jbutt#gmail.com",
"web": "http://www.bentonjohnbjr.com"
},
{
"id": 12,
"first_name": "Josephine",
"last_name": "Darakjy",
"company_name": "Chanay, Jeffrey A Esq",
"address": "4 B Blue Ridge Blvd",
"city": "Brighton",
"county": "Livingston",
"state": "MI",
"zip": 48116,
"phone1": "810-292-9388",
"phone2": "810-374-9840",
"email": "josephine_darakjy#darakjy.org",
"web": "http://www.chanayjeffreyaesq.com"
}
]);
$scope.tabs = [{
title: 'Issue List (0)'.replace("0", $scope.data1.length),
url: 'tab1.html'
}, {
title: 'Corrected (0)'.replace("0", $scope.data2.length),
url: 'tab2.html'
}];
$scope.currentTab = 'tab1.html';
$scope.onClickTab = function (tab) {
$scope.currentTab = tab.url;
}
$scope.isActiveTab = function (tabUrl) {
return tabUrl == $scope.currentTab;
}
$scope.changedata = function () {
$scope.data1.pop();
$scope.data2.pop();
console.log($scope.data1.length);
console.log($scope.data2.length);
}
}]);
Now this works fine when you are loading page for first time. Now on a button click ("Check" button), I am modifying the arrays. What should I do so that tab title is always in sync with length of arrays ? I have tried observable objects but unless I am using binding in view, they will just notify the event. Is there no other way except handling change event of observable arrays ?
you can Copy this piece of code inside the $scope.changedata function.
$scope.tabs = [{
title: 'Issue List (0)'.replace("0", $scope.data1.length),
url: 'tab1.html'
}, {
title: 'Corrected (0)'.replace("0", $scope.data2.length),
url: 'tab2.html'
}];
Also it remains outside as well.

Resources