如何从多个textareas和单选按钮上单击使用敲除按钮获取输入? [英] How to obtain input from multiple textareas and radio buttons on the click of a button using knockout?
问题描述
我有几个在 ko:foreach
绑定中动态生成的textareas和单选按钮。当用户决定他们完成输入时,他们将点击一个按钮'OK',该按钮将文本区的所有输入和他们选择的单选按钮的值全部输入,并且应该触发对服务器的ajax调用,因为输入需要存储在数据库中。每个textarea和radiobutton值都单独存储,因此需要将它们作为可区分的值发送到服务器。由于 foreach
绑定,我一直有很多麻烦,所以我不知道从哪里开始,因为textareas没有可访问的唯一标识符,因为它们是使用 foreach
生成。谢谢。
因此,简单来说:
- 多个用户类型textareas和点击单选按钮。
- 完成输入后,用户单击确定按钮。按钮点击功能可检索所有textareas和单选按钮值中的用户输入。
- 触发ajax调用并将值发送到服务器。
任何帮助表示赞赏或链接到我可以遵循的任何资源。我的谷歌搜索没有完全回答我的问题。
图片:
服务器:
if(Request.HttpMethod ==POST)
{
//将json放到body中
var serializer = new JsonSerializer();
var sr = new StreamReader(Request.InputStream);
var jtr = new JsonTextReader(sr);
dynamic data = serializer.Deserialize(jtr);
if(data.action ==getProjects)
{
getProjects(data);
$ b
通过ajax发布的示例对象:
Obj = {};
Obj.action =getProjects;
Obj.list = arrayOfCheckboxValues;
查看:
<! - ko foreach:projects - >
< div id =eachOppyProject>
< table>
< tbody>
< tr>
< td>< a data-bind =attr:{href:'/ tools / oppy /'+ guid}>< span class =linkdata-bind =value:guid ,text:name>< / span>< / a>< / td>
< / tr>
< tr data-bind =text:projectDescription>< / tr>
< / tbody>
< / table>
< div class =btn-groupdata-toggle =buttons>
< input type =radioclass =btn btn-default/>
它已经是
< / label>
< input type =radioclass =btn btn-default/>没有这样做,但感兴趣< / label>
< label class =btn btn-defaultdata-bind =visible:firstAnswers,click:function(){neverInterested(); showBtnOK();}>
< input type =radioclass =btn btn-default/>从来没有做过;不感兴趣< / label>
< / div>
< div data-bind =visible:doneAnswer>
class =form-control newSessionAnalystdata-bind =textInput:doneProject,attr:{id:guid,name:guid +'doneProject'}
/>
class =form-control newSessionAnalystdata-bind =textInput:doneProjectComment,attr:{id:guid,name:guid +'doneProjectComment'}/>
< / div>
< div data-bind =visible:interestedAnswer>
< textarea placeholder =所以,你有兴趣,嗯?告诉我们为什么。
class =form-control newSessionAnalystdata-bind =attr:{id:guid,name:guid +'interestedProject'}/>
class =form-control newSessionAnalystdata-bind =attr:{id:guid,name:guid +'interestedProjectComment'}/>
< / div>
< div class =btn-groupdata-toggle =buttons>
< label class =btn btn-defaultdata-bind =visible:doneAnswer,click:function(){showBtnOK(); showInterestedMoreTA();}>
< input type =radioclass =btn btn-default/>
有兴趣做更多< / label>
< input type =radioclass =btn btn-default/>
没有计划再次执行此操作< / label>
< / div>
< div data-bind =visible:interestedMore>
class =form-control newSessionAnalystdata-bind =attr:{id:guid,name:guid +'interestedMore'},value:$ parent.saved_value/>
class =form-control newSessionAnalystdata-bind =attr:{id:guid,name:guid +'interestedMoreComment'}/>
< / div>
< div style =text-align:right;>
< / div> //这是捕获所有输入的按钮
< / div>
<! - - / ko - >
查看模型:
function ViewModel(proj){
var self = this;
var wrappedProjects = proj.map(function(p){
return new Project(p);
});
self.projects = ko.observableArray(wrappedProjects);
}
函数Project(proj){
var self = proj;
self.firstAnswers = ko.observable(true);
self.doneAnswer = ko.observable(false);
self.showDoneTA = function(){
self.doneAnswer(true);
self.interestedAnswer(false);
}
self.interestedAnswer = ko.observable(false);
self.showInterestedTA = function(){
self.interestedAnswer(true);
self.doneAnswer(false);
self.interestedMore(false);
}
self.interestedMore = ko.observable(false);
self.showInterestedMoreTA = function(){
self.interestedMore(true);
}
self.notInterestedMore = function(){
self.interestedMore(false);
}
self.neverInterested = function(){
self.doneAnswer(false);
self.interestedAnswer(false);
self.interestedMore(false);
}
self.btnOK = ko.observable(false);
self.showBtnOK = function(){
self.btnOK(true);
console.log(self.btnOK());
}
self.savedMSG = ko.observable(false);
self.clearView = function(){
self.firstAnswers(false);
self.doneAnswer(false);
self.interestedAnswer(false);
self.interestedMore(false);
self.btnOK(false);
self.savedMSG(true);
}
self.showFirstAnswers = function(){
self.firstAnswers(true);
self.savedMSG(false);
}
返回自我;
在foreach中生成textareas是不是一个问题,他们不需要唯一的标识符。
我不知道是什么:
var wrappedProjects = proj.map(function(p){
return new Project(p);
});
确实如此,但假设它生成一个Projects数组,foreach很好。
我注意到并非所有的textareas都有值绑定,这会导致它们不会被填充值。
我确实看到了这个绑定:$ parent.saved_value。在这种情况下,$ parent将是ViewModel,并且没有定义。
我在使用foreach时遇到错误,直到我更改:
< textarea />
到:
< TextArea>< / textarea的>
淘汰赛引发了一个错误,指出该foreach未关闭。
我怀疑你是从jQuery思维模式接近的,因为你做这样的事情:
< textarea class =form-control newSessionAnalystdata-bind =textInput:doneProjectComment,attr:{id:guid,name:guid +'doneProjectComment'}/>
在我看来,你试图设置唯一的ID和名称,希望阅读当提交时,jQuery输入的val()。虽然我不知道你的 textInput
绑定是什么,但看起来 doneProjectComment
不是你的 Project
数据模型,因此输入到< textarea>
中的数据并不会真的在任何地方结束。
Knockout的方式是在 Project 中添加一个
doneProjectComment
,并使用值绑定它:
< textarea class =form-control newSessionAnalystdata-bind =value:doneProjectComment/>
函数Project(proj){
self.doneProjectComment = ko.observable();
}
Knockout为您提供了双向绑定。在 value:doneProjectComment
绑定的情况下,这意味着如果用户键入到textarea中,该值将被保存到 doneProjectComment
。如果 doneProjectComment
发生了变化,新的值会显示在textarea中。
Project
内部完成数据 - 只需读取你关心的所有观测值,然后创建一个散列<$ c $ 函数Project(proj){
self.toAjaxParameters = function(){
return {
interested:self.interestedAnswer(),
done:self.doneAnswer(),
...
$ b html:
如果您在ViewModel上设置了 save
函数
self.save = function(project){
$ .post('/ url-to-post-to',project.toAjaxParameters());
html:
< button data-bind =click:$ parent.save>< / button>
我建议安装 Knockout上下文调试器,它使调试敲除问题变得容易很多。
I have several textareas and radio buttons that are dynamically generated inside a ko: foreach
binding. When a user decides they are done typing their input, they will click a button 'OK' which takes all of the input of the textareas and values of the radio buttons they have chosen and it should trigger an ajax call to the server because the input needs to be stored in a database. Each textarea and radiobutton value is stored separately, so they need to be sent to the server as distinguished values. I've been having a lot of trouble given the foreach
binding, so I'm not sure where to begin because the textareas do not have an accessible unique identifier because they're generated using foreach
. Thank you.
So, in simpler terms:
- User types in multiple textareas and clicks on radio buttons.
- User clicks 'OK' button when finished typing. Button click function retrieves user input in all textareas and radio button values.
- Trigger ajax call and send values to server.
Any help is appreciated or links to any resources that I can follow. My google searches didn't quite answer my questions.
Picture:
Server:
//retrieves form data from the client and serialized it
if (Request.HttpMethod == "POST")
{
// get json out of body
var serializer = new JsonSerializer();
var sr = new StreamReader(Request.InputStream);
var jtr = new JsonTextReader(sr);
dynamic data = serializer.Deserialize(jtr);
if (data.action == "getProjects")
{
getProjects(data);
}
}
Example Object that is posted via ajax:
Obj = {};
Obj.action = "getProjects";
Obj.list = arrayOfCheckboxValues;
View:
<!-- ko foreach: projects -->
<div id="eachOppyProject">
<table>
<tbody>
<tr>
<td><a data-bind="attr: { href: '/tools/oppy/' + guid }"><span class="link" data-bind="value: guid, text: name"></span></a></td>
</tr>
<tr data-bind="text: projectDescription"></tr>
</tbody>
</table>
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-default" data-bind="visible: firstAnswers, click: function () { showBtnOK(); showDoneTA(); }">
<input type="radio" class="btn btn-default" />
Did it already
</label>
<label class="btn btn-default" data-bind="visible: firstAnswers, click: function () { showInterestedTA(); showBtnOK(); }">
<input type="radio" class="btn btn-default" />Didn't do it, but interested</label>
<label class="btn btn-default" data-bind="visible: firstAnswers, click: function () { neverInterested(); showBtnOK(); }">
<input type="radio" class="btn btn-default" />Never done it; not interested</label>
</div>
<div data-bind="visible: doneAnswer">
<textarea placeholder="Tell us a little of what you've done. Like, when did you do it? Who was in charge of it? Things like that."
class="form-control newSessionAnalyst" data-bind="textInput: doneProject, attr: { id: guid, name: guid + 'doneProject' }"
/>
<textarea placeholder="If there's anything else you'd like us to know, tell us here."
class="form-control newSessionAnalyst" data-bind="textInput: doneProjectComment, attr: { id: guid, name: guid + 'doneProjectComment' }"/>
</div>
<div data-bind="visible: interestedAnswer">
<textarea placeholder="So, you're interested, huh? Tell us why."
class="form-control newSessionAnalyst" data-bind="attr: { id: guid, name: guid + 'interestedProject' }"/>
<textarea placeholder="If there's anything else you'd like us to know, tell us here."
class="form-control newSessionAnalyst" data-bind="attr: { id: guid, name: guid + 'interestedProjectComment' }"/>
</div>
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-default" data-bind="visible: doneAnswer, click: function () { showBtnOK(); showInterestedMoreTA(); }">
<input type="radio" class="btn btn-default" />
Interested in doing more</label>
<label class="btn btn-default" data-bind="visible: doneAnswer, click: function () { showBtnOK(); notInterestedMore(); }">
<input type="radio" class="btn btn-default" />
No plans to do this again</label>
</div>
<div data-bind="visible: interestedMore">
<textarea placeholder="You want to do more? Way to go! Tell us more!"
class="form-control newSessionAnalyst" data-bind="attr: { id: guid, name: guid + 'interestedMore' }, value: $parent.saved_value"/>
<textarea placeholder="If there's anything else you'd like us to know, tell us here."
class="form-control newSessionAnalyst" data-bind="attr: { id: guid, name: guid + 'interestedMoreComment' }"/>
</div>
<div style="text-align: right;">
<input type="button" data-bind="visible: btnOK, click: function () { clearView(); }" value="OK" class="btn btn-default "/><br /><br />
</div> //this is the button that captures all input
</div>
<!-- /ko -->
View Model:
function ViewModel(proj) {
var self = this;
var wrappedProjects = proj.map(function (p) {
return new Project(p);
});
self.projects = ko.observableArray(wrappedProjects);
}
function Project(proj) {
var self = proj;
self.firstAnswers = ko.observable(true);
self.doneAnswer = ko.observable(false);
self.showDoneTA = function () {
self.doneAnswer(true);
self.interestedAnswer(false);
}
self.interestedAnswer = ko.observable(false);
self.showInterestedTA = function () {
self.interestedAnswer(true);
self.doneAnswer(false);
self.interestedMore(false);
}
self.interestedMore = ko.observable(false);
self.showInterestedMoreTA = function () {
self.interestedMore(true);
}
self.notInterestedMore = function () {
self.interestedMore(false);
}
self.neverInterested = function () {
self.doneAnswer(false);
self.interestedAnswer(false);
self.interestedMore(false);
}
self.btnOK = ko.observable(false);
self.showBtnOK = function () {
self.btnOK(true);
console.log(self.btnOK());
}
self.savedMSG = ko.observable(false);
self.clearView = function () {
self.firstAnswers(false);
self.doneAnswer(false);
self.interestedAnswer(false);
self.interestedMore(false);
self.btnOK(false);
self.savedMSG(true);
}
self.showFirstAnswers = function () {
self.firstAnswers(true);
self.savedMSG(false);
}
return self;
}
解决方案 Generating the textareas in a foreach is not a problem and they don't need unique identifiers.
I am not sure what:
var wrappedProjects = proj.map(function (p) {
return new Project(p);
});
does but assuming it generates an array of Projects, the foreach is fine.
I did notice not all of your textareas have value bindings which would cause them not to be populated with values.
I did see this binding:$parent.saved_value. In this case $parent would be ViewModel and that is not defined.
I was getting errors with the foreach until I changed the:
<textarea/>
to:
<textarea></textarea>
knockout was throwing an error stating the foreach was not closed.
I suspect you are approaching this from a "jQuery mindset", because you do things like this:
<textarea class="form-control newSessionAnalyst" data-bind="textInput: doneProjectComment, attr: { id: guid, name: guid + 'doneProjectComment' }"/>
It looks to me like you're try to set unique IDs and names, in the hope of reading the val() of the input with jQuery when it's time to submit. While I don't know what your textInput
binding is, it seems that doneProjectComment
is not an observable on your Project
data model, and thus the data entered in that <textarea>
doesn't really end up anywhere.
The Knockout way is to add a doneProjectComment
observable on your Project
, and bind to it with the value
binding:
<textarea class="form-control newSessionAnalyst" data-bind="value: doneProjectComment"/>
function Project(proj) {
self.doneProjectComment = ko.observable();
}
Knockout gives you two-way bindings. In case of the value: doneProjectComment
binding, this means that if the user types into the textarea, the value is saved into doneProjectComment
. If doneProjectComment
is changed, the new value is shown in the textarea.
So if you want to gather all the data when the user clicks 'ok', you can do it easily from inside the Project
- just read all the observables you care about, and create a hash that jQuery.post
can user as AJAX parameters:
function Project(proj) {
self.toAjaxParameters = function(){
return {
interested: self.interestedAnswer(),
done: self.doneAnswer(),
...
}
}
}
html:
If you setup a save
function on your ViewModel
self.save = function(project){
$.post('/url-to-post-to', project.toAjaxParameters());
}
html:
<button data-bind="click:$parent.save"></button>
I would suggest installing Knockout Context Debugger it makes debugging knockout problems a lot easier.
这篇关于如何从多个textareas和单选按钮上单击使用敲除按钮获取输入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!