Javascript angularjs中动态嵌套表单模型上的绑定数据
我从json对象(比如formObject)生成嵌套表单,并绑定json对象本身中的值。我递归地解析这些值,并在提交时提取实际数据,比如dataObject 我可以像这样以线性形式检索数据对象 这是一个解决方案&我可以在提交时获得,$scope.firstfiddle的答案(我认为)不允许这种嵌套。但是当我必须更新现有的数据对象时,我觉得有必要在呈现它之前将数据对象映射到formObject,然后在提交时再次解析。 现在这不是MVC,看起来不优雅(由于递归)&我认为这有一种“角度的方式”Javascript angularjs中动态嵌套表单模型上的绑定数据,javascript,angularjs,model-view-controller,Javascript,Angularjs,Model View Controller,我从json对象(比如formObject)生成嵌套表单,并绑定json对象本身中的值。我递归地解析这些值,并在提交时提取实际数据,比如dataObject 我可以像这样以线性形式检索数据对象 这是一个解决方案&我可以在提交时获得,$scope.firstfiddle的答案(我认为)不允许这种嵌套。但是当我必须更新现有的数据对象时,我觉得有必要在呈现它之前将数据对象映射到formObject,然后在提交时再次解析。 现在这不是MVC,看起来不优雅(由于递归)&我认为这有一种“角度的方式” 有没有
有没有人尝试过这一点&让它以更好的方式工作?我该如何解决这个问题呢?不是很好,但这是您已经提出的解决方案的替代方案
功能控制器($scope){
$scope.answers={};
$scope.tempOption=“”;
$scope.questions=[
{
“文本”:“性别?”,
“姓名”:“性别问题”,
“选项”:[“男性”、“女性”]},
{
“文本”:“最喜欢的颜色?”,
“名称”:“颜色问题”,
“选项”:[“红色”、“蓝色”、“绿色”]}
];
$scope.showAnswers=函数(){
log($scope.answers);
};
$scope.pumpOption=函数(名称,临时选项){
$scope.answers[name]=tempOption;
};
};
-
{{问题.文本}
我们将select标记中所选选项的值绑定到$scope.tempOption变量
然后,我们监听在这个select标记上发生的ng change事件,在这里我们运行一个函数,该函数使用$scope.tempOption变量加上与select标记关联的{question.name}
然后,此函数将answers[name]设置为当前值$scope.tempOption
希望这对你有用,祝你好运:)只需创建
$scope.Answer={}编码>并将ng模型链接到它 好的-这并不像我第一次想的那么简单,所以我希望这就是你想要的-你需要使用一个指令来动态生成它的模板HTML(更好的是,使用templateUrl和一个传入类型的函数)
TLDR:看到小提琴了吗
HTML非常简单
<div ng-controller="questionsController">
<!-- for each question, render section or question -->
<div ng-repeat="item in Questions">
<!-- we ignore section here as it's a root section -->
<question item="item"></question>
</div>
您需要创建一个指令来呈现问题和部分。它还需要跟踪该部分,以便构建答案
.directive('question', ['$compile', '$templateCache', function ($compile, $templateCache) {
var generateHtmlTemplate = function (item, section) {
return item.type != 'section' ?
// render the question
'question ' + item.name + '<br/>' +
'<select ng-model="optionValue" ng-options="opt for opt in item.options" ng-change="pushAnswer(item.name, section, optionValue)"></select>' :
// or the template for a section
'<br/><hr/>section ' + item.sectionName + '<br/>' +
'<div ng-repeat="q in item.questions"><question item="q" section="item"></question></div><hr/>';
}
var currentSection = null;
return {
scope: {
item: '=',
section: '='
},
restrict: 'E',
link: function ($scope, element, attrs) {
// check current section
if ($scope.item.type == 'section') {
// set new current section
$scope.currentSection = $scope.item;
} else {
// use section passed in from parent section
$scope.currentSection = $scope.section;
}
// get template html
var t = generateHtmlTemplate($scope.item, $scope.currentSection);
// set the scope function to set the value
$scope.pushAnswer = function (q, section, value) {
// build the Answers object here however you want...
if (section != null) {
console.log('pushAnswer q=' + q.name + ' - section=' + section.sectionName + ' - value=' + value);
} else {
console.log('pushAnswer q=' + q.name + ' - section=rootSection - value=' + value);
}
};
// chuck it into element as template
element.html(t);
// compile it up and return it
$compile(element.contents())($scope);
},
};
}])
.directive('question',['$compile','$templateCache',函数($compile,$templateCache){
var generateHtmlTemplate=函数(项,节){
return item.type!=“section”?
//提出问题
“问题”+item.name+“
”+
'' :
//或节的模板
“
section”+item.sectionName+”
”+
“
”;
}
var currentSection=null;
返回{
范围:{
项目:'=',
节:'='
},
限制:'E',
链接:函数($scope,element,attrs){
//检查当前部分
如果($scope.item.type=='section'){
//设置新的当前节
$scope.currentSection=$scope.item;
}否则{
//使用从父节传入的节
$scope.currentSection=$scope.section;
}
//获取模板html
var t=generateHtmlTemplate($scope.item,$scope.currentSection);
//设置范围函数以设置值
$scope.pushAnswer=函数(q、节、值){
//在此处创建您想要的答案对象。。。
if(节!=null){
log('pushAnswer q='+q.name+'-section='+section.sectionName+'-value='+value));
}否则{
log('pushAnswer q='+q.name+'-section=rootSection-value='+value);
}
};
//将其作为模板放入元素中
html(t);
//编译并返回它
$compile(element.contents())($scope);
},
};
}])
好吧,我是开玩笑的。
但是,您是否尝试过使用与平面相关的对象关系表方法而不是嵌套的方法
{
sections:[
{ "Name": 'Personal', "questions":[0], sub:[1] },
{ "Name": 'SubPersonal', "questions":[3], sub:[]},
{ "Name": 'Random', "questions":[1,2], sub:[] }
],
questions:[
{ "Name":"Gender", "Text":"Gender?", "Options":["Male", "Female"] },
{ "Name":"Color", "Text":"Favorite Color?", "Options":["Red","Blue","Green"] },
{ "Name":"LivingWith", "Text":"Living With?", "Options":["Alone","Someone"] },
{ "Name":"Random", "Text":"SectionLess", "Options":["opt1", "opt2"] }
]
}
是的,这是可行的,但是当我有嵌套对象的json数据时,递归下的情况看起来很糟糕。我现在有,但它不是MVC&通过相同的表单更新字段还有一些工作要做。我不太理解你的方法的问题。可能是因为JSFIDLE上的示例不够复杂-没有提到“递归”和“提交时再次解析”的需要-$scope。由于Angular的数据绑定,答案总是最新的,随时可以提交。但可能是因为我太困了:)不管怎样,如果你能把小提琴做得更精细一些(但不要太夸张,要欣赏hello worldish风格),以充分说明你当前方法的缺点,那就太酷了。正如@vucalur所说,我也不太明白小提琴有什么问题。我在示例中也没有看到任何递归。你能更新你的问题并更好地解释你的问题是什么吗?是的,试着解释一下!很抱歉第一次没有详细阐述问题陈述,我对简洁有一些奇怪的想法@vucalur,现在问题清楚了吗?或者我还需要进一步阐述吗?是的,这是一种方法,但它仍然不能解决筑巢的问题。例如,我不能使用答案[0]。值[0]。GenderQuestion
而不引用它的元素答案[0]。值[0]
。是的,但是我必须写一些东西来生成原始对象。我不想在平面表中表示我的数据模型!H
<div ng-controller="questionsController">
<!-- for each question, render section or question -->
<div ng-repeat="item in Questions">
<!-- we ignore section here as it's a root section -->
<question item="item"></question>
</div>
.directive('question', ['$compile', '$templateCache', function ($compile, $templateCache) {
var generateHtmlTemplate = function (item, section) {
return item.type != 'section' ?
// render the question
'question ' + item.name + '<br/>' +
'<select ng-model="optionValue" ng-options="opt for opt in item.options" ng-change="pushAnswer(item.name, section, optionValue)"></select>' :
// or the template for a section
'<br/><hr/>section ' + item.sectionName + '<br/>' +
'<div ng-repeat="q in item.questions"><question item="q" section="item"></question></div><hr/>';
}
var currentSection = null;
return {
scope: {
item: '=',
section: '='
},
restrict: 'E',
link: function ($scope, element, attrs) {
// check current section
if ($scope.item.type == 'section') {
// set new current section
$scope.currentSection = $scope.item;
} else {
// use section passed in from parent section
$scope.currentSection = $scope.section;
}
// get template html
var t = generateHtmlTemplate($scope.item, $scope.currentSection);
// set the scope function to set the value
$scope.pushAnswer = function (q, section, value) {
// build the Answers object here however you want...
if (section != null) {
console.log('pushAnswer q=' + q.name + ' - section=' + section.sectionName + ' - value=' + value);
} else {
console.log('pushAnswer q=' + q.name + ' - section=rootSection - value=' + value);
}
};
// chuck it into element as template
element.html(t);
// compile it up and return it
$compile(element.contents())($scope);
},
};
}])
var model = {
colors:["Red","Blue","Green","Black","White"],
genders:["Male", "Female"],
topic:["Gender", "Color"],
category:["Favorite", "Least favorite"],
};
function makeQuestion(topic, category){
return (category+1 ? model.category[category] + ' ' : '')
+ ' ' + model.topic[topic] + '?'
}
function QuestionController($scope){
$scope.Answers = {};
$scope.Questions = [
{
"Text": makeQuestion(0),
"Name": "GenderQuestion",
"Options": model.genders
},{
"Text": makeQuestion(1,0),
"Name": "ColorQuestion",
"Options": model.colors.slice(0,3)
},{
"Text": makeQuestion(0,1),
"Name": "SexistQuestion",
"Options": model.genders
},{
"Text": makeQuestion(1,1),
"Name": "RacistQuestion",
"Options":model.colors.slice(3)
}
];
$scope.ShowAnswers = function()
{
console.log($scope.Answers);
};
}
{
sections:[
{ "Name": 'Personal', "questions":[0], sub:[1] },
{ "Name": 'SubPersonal', "questions":[3], sub:[]},
{ "Name": 'Random', "questions":[1,2], sub:[] }
],
questions:[
{ "Name":"Gender", "Text":"Gender?", "Options":["Male", "Female"] },
{ "Name":"Color", "Text":"Favorite Color?", "Options":["Red","Blue","Green"] },
{ "Name":"LivingWith", "Text":"Living With?", "Options":["Alone","Someone"] },
{ "Name":"Random", "Text":"SectionLess", "Options":["opt1", "opt2"] }
]
}