Estou procurando a melhor abordagem para converter uma forma estática em uma forma dinâmica angular. Não tenho certeza de como vincular vários valores à mesma resposta.
A página estática está disponível em: 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>
O arquivo JSON
[
{
"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
]
}
]
Respostas:
0 para resposta № 1As coisas seriam muito mais simples se você pudesse usar uma seleção múltipla, mas eu entendo que pode ser difícil para o usuário interagir (considere algo como md-select, que transforma a seleção múltipla em uma lista de caixas de seleção para você)
Seleção múltipla:
<select multiple
ng-model="i.answer"
ng-options="o.id as o.title for o in i.answersAvailable"
ng-if="i.type == "MULTIPLE""></select>
De qualquer forma, está tudo bem usar a caixa de seleção HTML. Para fazer isso, precisaríamos vincular o modelo de caixa de seleção aos dados como de costume e, em seguida, atualizar a matriz de resposta simultaneamente.
ng-model="o.selected"
ng-change="updateAnswer(i)"
Além disso, precisaremos copiar os dados existentes para o modelo durante o init.
ng-init="initMultiple(i)"
Código de trabalho:
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>
0 para resposta № 2
Com base na minha experiência, farei uma separaçãocomo dois modelos angulares (ou geralmente chamados de serviços) para as perguntas do formulário e outro que coletará as respostas e, eventualmente, será passado para o backend para processamento posterior. Isso me dará flexibilidade para manter a lógica e a apresentação.
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;
});
A partir do exemplo de modelos de serviço acima, você precisa disponibilizá-los para sua apresentação por meio do controlador Angular com injeção de dependência.
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
});
O que você escreve na página HTML como uma visualização angular já está perto o suficiente. Você só precisa alterar a ligação para dois modelos, como proponho acima. Obrigada.