Angular 具有 JSON 对象的单页应用程序取决于另一个对象的选择
Angular Single Page App with JSON Object Depending on the Selection of Another
我正在整理一份问卷。每个问题都有三个选项可供选择。每个包含问题的对象都有另一个名为 'dependsOn' 的对象。
例如,如果在问题 1 上选择 "Yes",则将显示以下两个问题,否则将跳过它们。
感谢您对这个小应用程序的任何帮助、想法和建议。
这是我放在一起的 CodePen:my codepen
<div class="main" ng-app="MyApp">
<div ng-controller="AppCtrl as q">
<h1>{{ q.title }}</h1>
<form name="collection" novalidate>
<div class="questionnaire">
<div class="questions">
<div class="question" ng-repeat="question in q.questions" ng-show="question.hrsQuestionOrderNumber === q.currentQuestion">
<h2>Question {{ question.hrsQuestionOrderNumber }} <span>of {{ q.questions.length }}</span></h2>
<p>
{{ question.descriptionLong }}
</p>
<ng-form name="subForm{{question.questionID}}" class="options">
<md-radio-group ng-model="question.hrsAnswerId" ng-change="q.watchForm(subForm{{ q.currentQuestion }})" required>
<md-radio-button ng-repeat="option in question.choiceModels" ng-value="option.description" required>
{{ option.description }}
</md-radio-button>
</md-radio-group>
</ng-form>
</div>
</div>
<nav class="clearfix">
<md-button class="md-primary md-raised" ng-click="q.questionChange('prev')" ng-disabled="q.prev">Previous</md-button>
<md-button class="md-primary md-raised" ng-click="q.questionChange('next')" ng-disabled="q.next">Next</md-button>
</nav>
</div>
</form>
Angular代码:
angular
.module('MyApp',['ngMaterial', 'ngMessages'])
.controller('AppCtrl', function($timeout, $scope) {
const context = this;
context.title = 'Questionnaire with Questions Depending on Choices';
context.currentQuestion = 1;
context.next = true;
context.prev = true;
context.nextButton = true;
context.form = $scope.collection;
function disableButton () {
if (context.currentQuestion === 1) {
context.prev = true;
context.next = false;
} else {
context.prev = false;
context.next = false;
}
};
context.questionChange = function (go) {
if (go === 'prev') {
context.currentQuestion = context.currentQuestion - 1;
}
if (go === 'next') {
context.currentQuestion = context.currentQuestion + 1;
$timeout(function () {
context.next = true;
});
}
disableButton();
};
context.watchForm = function (currentForm) {
if (currentForm.$invalid === false) {
if (context.currentQuestion !== context.questions.length) {
context.next = false;
}
} else {
console.log('form NOT in scope');
}
};
context.questions = [
{
"questionID": 1,
"hrsQuestionOrderNumber": 1,
"descriptionLong": "Do you collect money from anyone (students, employees, or other sources)?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1
},
{
"description": "No",
"answerId": 1
},
{
"description": "None / Not applicable",
"answerId": 3
}
],
"dependsOn": null
},
{
"questionID": 2,
"hrsQuestionOrderNumber": 2,
"descriptionLong": "Are pre-numbered receipts given to the person paying money? If individual receipts are not given, do you use an approved PBO/S&I collection document?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1
},
{
"description": "No",
"answerId": 1
},
{
"description": "None / Not applicable",
"answerId": 3
}
],
"dependsOn": {
"hrsQuestionId": 0,
"hrsQuestionLink": 1,
"hrsAnswerId": 1
}
},
{
"questionID": 3,
"hrsQuestionOrderNumber": 3,
"descriptionLong": "Do cash receipts or logs contain sufficient detail to accurately describe the nature of the transaction?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1
},
{
"description": "No",
"answerId": 1
},
{
"description": "None / Not applicable",
"answerId": 3
}
],
"dependsOn": {
"hrsQuestionId": 0,
"hrsQuestionLink": 1,
"hrsAnswerId": 1
}
},
{
"questionID": 4,
"hrsQuestionOrderNumber": 4,
"descriptionLong": "Do receipts or logs identify individuals and not groups of individuals (such as a class)?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1
},
{
"description": "No",
"answerId": 1
},
{
"description": "None / Not applicable",
"answerId": 3
}
],
"dependsOn": null
},
{
"questionID": 5,
"hrsQuestionOrderNumber": 5,
"descriptionLong": "For money collected, is it always deposited and never used for purchases?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1
},
{
"description": "No",
"answerId": 1
},
{
"description": "None / Not applicable",
"answerId": 3
}
],
"dependsOn": {
"hrsQuestionId": 0,
"hrsQuestionLink": 4,
"hrsAnswerId": 1
}
},
{
"questionID": 6,
"hrsQuestionOrderNumber": 6,
"descriptionLong": "For money not yet deposited, is it kept in a secure location?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1
},
{
"description": "No",
"answerId": 1
},
{
"description": "None / Not applicable",
"answerId": 3
}
],
"dependsOn": {
"hrsQuestionId": 0,
"hrsQuestionLink": 4,
"hrsAnswerId": 1
}
},
{
"questionID": 7,
"hrsQuestionOrderNumber": 7,
"descriptionLong": "Do you keep a file of original deposit documentation—including cash receipts or logs—together?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1
},
{
"description": "No",
"answerId": 1
},
{
"description": "None / Not applicable",
"answerId": 3
}
],
"dependsOn": {
"hrsQuestionId": 0,
"hrsQuestionLink": 4,
"hrsAnswerId": 1
}
}
];
})
.config(function($mdIconProvider) {
});
我不明白你的问题是什么?
创建将包含问题数量作为键和答案索引作为值的对象
{'1': 1, '2': 0, ...}
- 每次回答后,您只需浏览一系列问题,select下一个问题取决于用户选择的内容。
我的解决方案是遍历问题并评估问题是否取决于所选答案。这使得可以根据所选答案跳过一些问题。
这是我的 CodePen:My CodePend
angular
.module('MyApp', ['ngMaterial', 'ngMessages'])
.controller('AppCtrl', function ($timeout, $scope, $filter) {
const context = this;
context.title = 'Questions Depending on Choices';
context.heading = 'Questionnaire';
context.currentQuestion = 1;
context.next = true;
context.prev = true;
context.nextButton = true;
function disableButton() {
if (context.currentQuestion === 1) {
context.prev = true;
context.next = false;
} else {
context.prev = false;
context.next = false;
}
};
context.questionChange = function(go) {
if (go === 'prev') {
context.currentQuestion = context.currentQuestion - 1;
//Go to the prev (in order) that has an selectedAnswer
var prevQuestions = $filter("filter")(context.questions, { "hrsQuestionOrderNumber": context.currentQuestion });
if (!prevQuestions[0].hrsAnswerId) {
context.questionChange(go);
}
}
if (go === 'next') {
//in order - check the dependsOn for Q&a required
context.currentQuestion = context.currentQuestion + 1;
var nextQuestions = $filter("filter")(context.questions, { "hrsQuestionOrderNumber": context.currentQuestion });
if (nextQuestions.length > 0) {
var dependsOn = nextQuestions[0].dependsOn;
if (dependsOn) {
var dependentQuestions = $filter("filter")(context.questions, { "questionID": dependsOn.hrsQuestionLink });
if (dependentQuestions[0].hrsAnswerId !== dependsOn.hrsAnswerId) {
context.questionChange(go);
}
}
}
$timeout(function () {
context.next = true;
});
}
disableButton();
};
context.watchForm = function(currentForm) {
if (currentForm.$invalid === false) {
if (context.currentQuestion !== context.questions.length) {
context.next = false;
}
} else {
console.log('form NOT in scope');
}
};
context.questions = [
{
"questionID": 1533,
"hrsQuestionOrderNumber": 1,
"descriptionLong": "Do you collect money from anyone (students, employees, or other sources)?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1000
},
{
"description": "No",
"answerId": 1001
},
{
"description": "None / Not applicable",
"answerId": 1148
}
],
"dependsOn": null
},
{
"questionID": 1534,
"hrsQuestionOrderNumber": 2,
"descriptionLong": "Are pre-numbered receipts given to the person paying money? If individual receipts are not given, do you use an approved PBO/S&I collection document?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1000
},
{
"description": "No",
"answerId": 1001
},
{
"description": "None / Not applicable",
"answerId": 1148
}
],
"dependsOn": {
"hrsQuestionId": 0,
"hrsQuestionLink": 1533,
"hrsAnswerId": 1000
}
},
{
"questionID": 1535,
"hrsQuestionOrderNumber": 3,
"descriptionLong": "Do cash receipts or logs contain sufficient detail to accurately describe the nature of the transaction?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1000
},
{
"description": "No",
"answerId": 1001
},
{
"description": "None / Not applicable",
"answerId": 1148
}
],
"dependsOn": {
"hrsQuestionId": 0,
"hrsQuestionLink": 1533,
"hrsAnswerId": 1000
}
},
{
"questionID": 1536,
"hrsQuestionOrderNumber": 4,
"descriptionLong": "Do receipts or logs identify individuals and not groups of individuals (such as a class)?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1000
},
{
"description": "No",
"answerId": 1001
},
{
"description": "None / Not applicable",
"answerId": 1148
}
],
"dependsOn": null
},
{
"questionID": 1537,
"hrsQuestionOrderNumber": 5,
"descriptionLong": "For money collected, is it always deposited and never used for purchases?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1000
},
{
"description": "No",
"answerId": 1001
},
{
"description": "None / Not applicable",
"answerId": 1148
}
],
"dependsOn": {
"hrsQuestionId": 0,
"hrsQuestionLink": 1536,
"hrsAnswerId": 1000
}
},
{
"questionID": 1538,
"hrsQuestionOrderNumber": 6,
"descriptionLong": "For money not yet deposited, is it kept in a secure location?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1000
},
{
"description": "No",
"answerId": 1001
},
{
"description": "None / Not applicable",
"answerId": 1148
}
],
"dependsOn": {
"hrsQuestionId": 0,
"hrsQuestionLink": 1536,
"hrsAnswerId": 1000
}
},
{
"questionID": 1539,
"hrsQuestionOrderNumber": 7,
"descriptionLong": "Do you keep a file of original deposit documentation—including cash receipts or logs—together?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1000
},
{
"description": "No",
"answerId": 1001
},
{
"description": "None / Not applicable",
"answerId": 1148
}
],
"dependsOn": {
"hrsQuestionId": 0,
"hrsQuestionLink": 1536,
"hrsAnswerId": 1000
}
}
];
})
.config(function($mdIconProvider) {
});
我正在整理一份问卷。每个问题都有三个选项可供选择。每个包含问题的对象都有另一个名为 'dependsOn' 的对象。 例如,如果在问题 1 上选择 "Yes",则将显示以下两个问题,否则将跳过它们。 感谢您对这个小应用程序的任何帮助、想法和建议。 这是我放在一起的 CodePen:my codepen
<div class="main" ng-app="MyApp">
<div ng-controller="AppCtrl as q">
<h1>{{ q.title }}</h1>
<form name="collection" novalidate>
<div class="questionnaire">
<div class="questions">
<div class="question" ng-repeat="question in q.questions" ng-show="question.hrsQuestionOrderNumber === q.currentQuestion">
<h2>Question {{ question.hrsQuestionOrderNumber }} <span>of {{ q.questions.length }}</span></h2>
<p>
{{ question.descriptionLong }}
</p>
<ng-form name="subForm{{question.questionID}}" class="options">
<md-radio-group ng-model="question.hrsAnswerId" ng-change="q.watchForm(subForm{{ q.currentQuestion }})" required>
<md-radio-button ng-repeat="option in question.choiceModels" ng-value="option.description" required>
{{ option.description }}
</md-radio-button>
</md-radio-group>
</ng-form>
</div>
</div>
<nav class="clearfix">
<md-button class="md-primary md-raised" ng-click="q.questionChange('prev')" ng-disabled="q.prev">Previous</md-button>
<md-button class="md-primary md-raised" ng-click="q.questionChange('next')" ng-disabled="q.next">Next</md-button>
</nav>
</div>
</form>
Angular代码:
angular
.module('MyApp',['ngMaterial', 'ngMessages'])
.controller('AppCtrl', function($timeout, $scope) {
const context = this;
context.title = 'Questionnaire with Questions Depending on Choices';
context.currentQuestion = 1;
context.next = true;
context.prev = true;
context.nextButton = true;
context.form = $scope.collection;
function disableButton () {
if (context.currentQuestion === 1) {
context.prev = true;
context.next = false;
} else {
context.prev = false;
context.next = false;
}
};
context.questionChange = function (go) {
if (go === 'prev') {
context.currentQuestion = context.currentQuestion - 1;
}
if (go === 'next') {
context.currentQuestion = context.currentQuestion + 1;
$timeout(function () {
context.next = true;
});
}
disableButton();
};
context.watchForm = function (currentForm) {
if (currentForm.$invalid === false) {
if (context.currentQuestion !== context.questions.length) {
context.next = false;
}
} else {
console.log('form NOT in scope');
}
};
context.questions = [
{
"questionID": 1,
"hrsQuestionOrderNumber": 1,
"descriptionLong": "Do you collect money from anyone (students, employees, or other sources)?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1
},
{
"description": "No",
"answerId": 1
},
{
"description": "None / Not applicable",
"answerId": 3
}
],
"dependsOn": null
},
{
"questionID": 2,
"hrsQuestionOrderNumber": 2,
"descriptionLong": "Are pre-numbered receipts given to the person paying money? If individual receipts are not given, do you use an approved PBO/S&I collection document?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1
},
{
"description": "No",
"answerId": 1
},
{
"description": "None / Not applicable",
"answerId": 3
}
],
"dependsOn": {
"hrsQuestionId": 0,
"hrsQuestionLink": 1,
"hrsAnswerId": 1
}
},
{
"questionID": 3,
"hrsQuestionOrderNumber": 3,
"descriptionLong": "Do cash receipts or logs contain sufficient detail to accurately describe the nature of the transaction?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1
},
{
"description": "No",
"answerId": 1
},
{
"description": "None / Not applicable",
"answerId": 3
}
],
"dependsOn": {
"hrsQuestionId": 0,
"hrsQuestionLink": 1,
"hrsAnswerId": 1
}
},
{
"questionID": 4,
"hrsQuestionOrderNumber": 4,
"descriptionLong": "Do receipts or logs identify individuals and not groups of individuals (such as a class)?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1
},
{
"description": "No",
"answerId": 1
},
{
"description": "None / Not applicable",
"answerId": 3
}
],
"dependsOn": null
},
{
"questionID": 5,
"hrsQuestionOrderNumber": 5,
"descriptionLong": "For money collected, is it always deposited and never used for purchases?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1
},
{
"description": "No",
"answerId": 1
},
{
"description": "None / Not applicable",
"answerId": 3
}
],
"dependsOn": {
"hrsQuestionId": 0,
"hrsQuestionLink": 4,
"hrsAnswerId": 1
}
},
{
"questionID": 6,
"hrsQuestionOrderNumber": 6,
"descriptionLong": "For money not yet deposited, is it kept in a secure location?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1
},
{
"description": "No",
"answerId": 1
},
{
"description": "None / Not applicable",
"answerId": 3
}
],
"dependsOn": {
"hrsQuestionId": 0,
"hrsQuestionLink": 4,
"hrsAnswerId": 1
}
},
{
"questionID": 7,
"hrsQuestionOrderNumber": 7,
"descriptionLong": "Do you keep a file of original deposit documentation—including cash receipts or logs—together?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1
},
{
"description": "No",
"answerId": 1
},
{
"description": "None / Not applicable",
"answerId": 3
}
],
"dependsOn": {
"hrsQuestionId": 0,
"hrsQuestionLink": 4,
"hrsAnswerId": 1
}
}
];
})
.config(function($mdIconProvider) {
});
我不明白你的问题是什么?
创建将包含问题数量作为键和答案索引作为值的对象
{'1': 1, '2': 0, ...}
- 每次回答后,您只需浏览一系列问题,select下一个问题取决于用户选择的内容。
我的解决方案是遍历问题并评估问题是否取决于所选答案。这使得可以根据所选答案跳过一些问题。 这是我的 CodePen:My CodePend
angular
.module('MyApp', ['ngMaterial', 'ngMessages'])
.controller('AppCtrl', function ($timeout, $scope, $filter) {
const context = this;
context.title = 'Questions Depending on Choices';
context.heading = 'Questionnaire';
context.currentQuestion = 1;
context.next = true;
context.prev = true;
context.nextButton = true;
function disableButton() {
if (context.currentQuestion === 1) {
context.prev = true;
context.next = false;
} else {
context.prev = false;
context.next = false;
}
};
context.questionChange = function(go) {
if (go === 'prev') {
context.currentQuestion = context.currentQuestion - 1;
//Go to the prev (in order) that has an selectedAnswer
var prevQuestions = $filter("filter")(context.questions, { "hrsQuestionOrderNumber": context.currentQuestion });
if (!prevQuestions[0].hrsAnswerId) {
context.questionChange(go);
}
}
if (go === 'next') {
//in order - check the dependsOn for Q&a required
context.currentQuestion = context.currentQuestion + 1;
var nextQuestions = $filter("filter")(context.questions, { "hrsQuestionOrderNumber": context.currentQuestion });
if (nextQuestions.length > 0) {
var dependsOn = nextQuestions[0].dependsOn;
if (dependsOn) {
var dependentQuestions = $filter("filter")(context.questions, { "questionID": dependsOn.hrsQuestionLink });
if (dependentQuestions[0].hrsAnswerId !== dependsOn.hrsAnswerId) {
context.questionChange(go);
}
}
}
$timeout(function () {
context.next = true;
});
}
disableButton();
};
context.watchForm = function(currentForm) {
if (currentForm.$invalid === false) {
if (context.currentQuestion !== context.questions.length) {
context.next = false;
}
} else {
console.log('form NOT in scope');
}
};
context.questions = [
{
"questionID": 1533,
"hrsQuestionOrderNumber": 1,
"descriptionLong": "Do you collect money from anyone (students, employees, or other sources)?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1000
},
{
"description": "No",
"answerId": 1001
},
{
"description": "None / Not applicable",
"answerId": 1148
}
],
"dependsOn": null
},
{
"questionID": 1534,
"hrsQuestionOrderNumber": 2,
"descriptionLong": "Are pre-numbered receipts given to the person paying money? If individual receipts are not given, do you use an approved PBO/S&I collection document?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1000
},
{
"description": "No",
"answerId": 1001
},
{
"description": "None / Not applicable",
"answerId": 1148
}
],
"dependsOn": {
"hrsQuestionId": 0,
"hrsQuestionLink": 1533,
"hrsAnswerId": 1000
}
},
{
"questionID": 1535,
"hrsQuestionOrderNumber": 3,
"descriptionLong": "Do cash receipts or logs contain sufficient detail to accurately describe the nature of the transaction?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1000
},
{
"description": "No",
"answerId": 1001
},
{
"description": "None / Not applicable",
"answerId": 1148
}
],
"dependsOn": {
"hrsQuestionId": 0,
"hrsQuestionLink": 1533,
"hrsAnswerId": 1000
}
},
{
"questionID": 1536,
"hrsQuestionOrderNumber": 4,
"descriptionLong": "Do receipts or logs identify individuals and not groups of individuals (such as a class)?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1000
},
{
"description": "No",
"answerId": 1001
},
{
"description": "None / Not applicable",
"answerId": 1148
}
],
"dependsOn": null
},
{
"questionID": 1537,
"hrsQuestionOrderNumber": 5,
"descriptionLong": "For money collected, is it always deposited and never used for purchases?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1000
},
{
"description": "No",
"answerId": 1001
},
{
"description": "None / Not applicable",
"answerId": 1148
}
],
"dependsOn": {
"hrsQuestionId": 0,
"hrsQuestionLink": 1536,
"hrsAnswerId": 1000
}
},
{
"questionID": 1538,
"hrsQuestionOrderNumber": 6,
"descriptionLong": "For money not yet deposited, is it kept in a secure location?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1000
},
{
"description": "No",
"answerId": 1001
},
{
"description": "None / Not applicable",
"answerId": 1148
}
],
"dependsOn": {
"hrsQuestionId": 0,
"hrsQuestionLink": 1536,
"hrsAnswerId": 1000
}
},
{
"questionID": 1539,
"hrsQuestionOrderNumber": 7,
"descriptionLong": "Do you keep a file of original deposit documentation—including cash receipts or logs—together?",
"choiceModels": [
{
"description": "Yes",
"answerId": 1000
},
{
"description": "No",
"answerId": 1001
},
{
"description": "None / Not applicable",
"answerId": 1148
}
],
"dependsOn": {
"hrsQuestionId": 0,
"hrsQuestionLink": 1536,
"hrsAnswerId": 1000
}
}
];
})
.config(function($mdIconProvider) {
});