gpt4 book ai didi

forms - 在 Marionette js 中处理单选按钮表单

转载 作者:行者123 更新时间:2023-12-01 09:34:31 25 4
gpt4 key购买 nike

我正在尝试在我的应用程序中构建一个 View ,该 View 将在模态对话框区域中弹出投票问题。例如,可能是这样的:

    What is your favorite color?

>Red
>Blue
>Green
>Yellow
>Other

Submit Vote

我了解到 Marionette js 不支持开箱即用的表单,建议您自行处理。

上面的结构,分支和叶子(问题和选项列表)向我建议了 CompositeView。对吗?

如何触发 model.save() 来记录选择?一个 html 表单需要一个 Action 。我不清楚如何将表单操作连接到 model.save()。

我的草稿 ItemView 和 CompositeView 代码如下。我在球场上吗?应该如何调整?

var PollOptionItemView = Marionette.ItemView.extend({
template: Handlebars.compile(
'<input type="radio" name="group{{pollNum}}" value="{{option}}">{{option}}<br>'
)
});


var PollOptionsListView = Marionette.CompositeView.extend({
template: Handlebars.compile(

//The question part
'<div id="poll">' +
'<div>{{question}}</div>' +
'</div>' +

//The list of options part
'<form name="pollQuestion" action="? what goes here ?">' +
'<div id="poll-options">' +
'</div>' +
'<input type="submit" value="Submit your vote">' +
'</form>'
),

itemView: PollOptionItemView,

appendHtml: function (compositeView, itemView, index) {
var childrenContainer = $(compositeView.$("#poll-options") || compositeView.el);
var children = childrenContainer.children();
if (children.size() === index) {
childrenContainer.append(itemView.el);
} else {
childrenContainer.children().eq(index).before(itemView.el);
}
}
});

更多详情:

我的目标实际上是动态构建投票问题,这意味着问题和选项在运行时是未知的,而是之后从 SQL 数据库中查询的。如果您正在查看我的应用程序,我会通过 SignalR 在您的屏幕上发起投票。本质上,我是在告诉您的浏览器“嘿,去从数据库中获取民意调查问题 #1 的内容并显示它们”。我的想法是 CompositeViews 最适合这个,因为它们是数据驱动的。问题和相应的选项可以是存储的模型和集合,CompositeView 模板可以根据需要动态呈现它们。我有大部分有线,看起来不错。我唯一的问题似乎是要呈现哪种模板的概念。表单?或者我的模板应该只是在屏幕上放置一些单选按钮,下面有一个提交按钮,然后我编写一些 javascript 来尝试确定用户做出的选择?我根本不想使用表单,只使用 Backbone 框架来处理提交。这对我来说似乎很干净,但也许不可能或不明智?还不确定。

最佳答案

我会使用以下方法:

  • 收集您的调查问题
  • 为每种类型的问题创建特殊的项目 View
  • 在您的 CompositeView 中,根据其类型选择模型 itemView
  • 使用简单的验证来查看是否已回答所有问题
  • 输出所有问题及其结果的数组。

有关示例实现,请参阅此 fiddle :http://jsfiddle.net/Cardiff/QRdhT/
全屏:http://jsfiddle.net/Cardiff/QRdhT/embedded/result/

注意:

  • 在不回答所有问题的情况下尝试一下,看看效果如何
  • 成功后检查您的控制台以查看结果

代码

// Define data
var surveyData = [{
id: 1,
type: 'multiplechoice',
question: 'What color do you like?',
options: ["Red", "Green", "Insanely blue", "Yellow?"],
result: null,
validationmsg: "Please choose a color."
}, {
id: 2,
type: 'openquestion',
question: 'What food do you like?',
options: null,
result: null,
validationmsg: "Please explain what food you like."
}, {
id: 3,
type: 'checkbox',
question: 'What movie genres do you prefer?',
options: ["Comedy", "Action", "Awesome", "Adventure", "1D"],
result: null,
validationmsg: "Please choose at least one movie genre."
}];

// Setup models
var questionModel = Backbone.Model.extend({
defaults: {
type: null,
question: "",
options: null,
result: null,
validationmsg: "Please fill in this question."
},
validate: function () {
// Check if a result has been set, if not, invalidate
if (!this.get('result')) {
return false;
}
return true;
}
});

// Setup collection
var surveyCollection = Backbone.Collection.extend({
model: questionModel
});
var surveyCollectionInstance = new surveyCollection(surveyData);
console.log(surveyCollectionInstance);

// Define the ItemViews
/// Base itemView
var baseSurveyItemView = Marionette.ItemView.extend({
ui: {
warningmsg: '.warningmsg',
panel: '.panel'
},
events: {
'change': 'storeResult'
},
modelEvents: {
'showInvalidMessage': 'showInvalidMessage',
'hideInvalidMessage': 'hideInvalidMessage'
},
showInvalidMessage: function() {
// Show message
this.ui.warningmsg.show();

// Add warning class
this.ui.panel.addClass('panel-warningborder');
},
hideInvalidMessage: function() {
// Hide message
this.ui.warningmsg.hide();

// Remove warning class
this.ui.panel.removeClass('panel-warningborder');
}
});

/// Specific views
var multipleChoiceItemView = baseSurveyItemView.extend({
template: "#view-multiplechoice",
storeResult: function() {
var value = this.$el.find("input[type='radio']:checked").val();
this.model.set('result', value);
}
});

var openQuestionItemView = baseSurveyItemView.extend({
template: "#view-openquestion",
storeResult: function() {
var value = this.$el.find("textarea").val();
this.model.set('result', value);
}
});

var checkBoxItemView = baseSurveyItemView.extend({
template: "#view-checkbox",
storeResult: function() {
var value = $("input[type='checkbox']:checked").map(function(){
return $(this).val();
}).get();
this.model.set('result', (_.isEmpty(value)) ? null : value);
}
});

// Define a CompositeView
var surveyCompositeView = Marionette.CompositeView.extend({
template: "#survey",
ui: {
submitbutton: '.btn-primary'
},
events: {
'click @ui.submitbutton': 'submitSurvey'
},
itemViewContainer: ".questions",
itemViews: {
multiplechoice: multipleChoiceItemView,
openquestion: openQuestionItemView,
checkbox: checkBoxItemView
},
getItemView: function (item) {
// Get the view key for this item
var viewId = item.get('type');

// Get all defined views for this CompositeView
var itemViewObject = Marionette.getOption(this, "itemViews");

// Get correct view using given key
var itemView = itemViewObject[viewId];


if (!itemView) {
throwError("An `itemView` must be specified", "NoItemViewError");
}
return itemView;
},
submitSurvey: function() {
// Check if there are errors
var hasErrors = false;
_.each(this.collection.models, function(m) {
// Validate model
var modelValid = m.validate();

// If it's invalid, trigger event on model
if (!modelValid) {
m.trigger('showInvalidMessage');
hasErrors = true;
}
else {
m.trigger('hideInvalidMessage');
}
});

// Check to see if it has errors, if so, raise message, otherwise output.
if (hasErrors) {
alert('You haven\'t answered all questions yet, please check.');
}
else {
// No errors, parse results and log to console
var surveyResult = _.map(this.collection.models, function(m) {
return {
id: m.get('id'),
result: m.get('result')
}
});

// Log to console
alert('Success! Check your console for the results');
console.log(surveyResult);

// Close the survey view
rm.get('container').close();
}
}
});

// Create a region
var rm = new Marionette.RegionManager();
rm.addRegion("container", "#container");

// Create instance of composite view
var movieCompViewInstance = new surveyCompositeView({
collection: surveyCollectionInstance
});

// Show the survey
rm.get('container').show(movieCompViewInstance);

模板

<script type="text/html" id="survey">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title" > A cool survey regarding your life </h3>
</div>
<div class="panel-body">
<div class="questions"></div>
<div class="submitbutton">
<button type="button" class="btn btn-primary">Submit survey!</button>
</div>
</div>
</div >
</script>

<script type="text/template" id="view-multiplechoice">
<div class="panel panel-success">
<div class="panel-heading">
<h4 class="panel-title" > <%= question %> </h4>
</div>
<div class="panel-body">
<div class="warningmsg"><%= validationmsg %></div>
<% _.each( options, function( option, index ){ %>
<div class="radio">
<label>
<input type="radio" name="optionsRadios" id="<%= index %>" value="<%= option %>"> <%= option %>
</label>
</div>
<% }); %>
</div>
</div>
</script>

<script type="text/template" id="view-openquestion">
<div class="panel panel-success">
<div class="panel-heading">
<h4 class="panel-title" > <%= question %> </h4>
</div>
<div class="panel-body">
<div class="warningmsg"><%= validationmsg %></div>
<textarea class="form-control" rows="3"></textarea>
</div>
</div >
</script>

<script type="text/template" id="view-checkbox">
<div class="panel panel-success">
<div class="panel-heading">
<h4 class="panel-title" > <%= question %> </h4>
</div>
<div class="panel-body">
<div class="warningmsg"><%= validationmsg %></div>
<% _.each( options, function( option, index ){ %>
<div class="checkbox">
<label>
<input type="checkbox" value="<%= option %>"> <%= option %>
</label>
</div>
<% }); %>
</div>
</div>
</script>

<div id="container"></div>

更新:添加了 Handlebars 示例
Jsfiddle 使用 Handlebars :http://jsfiddle.net/Cardiff/YrEP8/

关于forms - 在 Marionette js 中处理单选按钮表单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23529056/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com