如何使用KnockoutJS在单个单选按钮上使用多个已检查数据?

时间:2016-07-11 17:54:17

标签: javascript jquery python ajax knockout.js

用户需要选择一个单选按钮。我的标签需要具有所选单选按钮的值,以便稍后在文本框中显示。我还需要将单选按钮的值存储在Ajax"标题"变量,以便我可以在后端使用它(Python - Flask)。当我单击我的迁移按钮时,它会运行我的Ajax调用。

我读到我可以在数据绑定之间添加逗号,但通过执行data-bind="checked: $data.title, checked: radioFrom",它会将我的代码分解到单选按钮不起作用的位置。但是,如果我只做data-bind="checked: $data.title",那么我的Ajax调用就可以了,但我的标签仍然是空白的(原因很明显)。

如何获取它以便我可以在单选按钮上使用两个已检查的数据绑定,以便我的标签更新和我的Ajax调用工作?还是我还缺少另一种解决方案?

我的标题

<!DOCTYPE html>
<html>

    <script type='text/javascript' src='http://ajax.aspnetcdn.com/ajax/knockout/knockout-3.4.0.js'></script>
    <script type='text/javascript' src='https://cdnjs.cloudflare.com/ajax/libs/json2/20150503/json2.js'></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
    <script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">

    <body>  
        {% extends "layout.html" %}
        {% block content %}
        <div id="tab">

我的收音机按钮

<td id="myRadioFrom" class="label">From:</td>
<td>
    <label><input type="radio" value="DevQ" name="from" data-bind="checked: $data.title, checked: radioFrom" />DevQ</label>
    <label><input type="radio" value="Dev2" name="from" data-bind="checked: $data.title, checked: radioFrom" />Dev2</label>
</td>

我的标签

<tr>
    <td class="label">From:</td>
    <td data-bind="text: radioFrom"></td>
</tr>

我的按钮

<form>
    <span class="migrate"><button data-bind="click: $data.add" type="submit" class="btn btn-default" value="Migrate!" data-dismiss="modal">Migrate!</button></span>
</form>

我的Javascript / KnockoutJS

<script>
    var TabViewModel = function(){
        var self = this;

        //Set href value of element
        self.selected = ko.observable(null);

        self.tasksURI = 'http://localhost:5000/todo/api/v1.0/tasks';    // Use to get root access to server
        self.username = "";
        self.password = "";
        self.tasks = ko.observableArray();

        self.radioFrom = ko.observable("");

        var btn = document.getElementById("myBtn");                 
        var span = document.getElementsByClassName("close")[0];

        controls.onchange = function() {
            console.log(viewModel.radioFrom());
        }

        self.ajax = function(uri, method, data)
        {
            var request = 
            {
                url: uri,
                type: method,
                contentType: "application/json",
                accepts: "application/json",
                cache: false,
                dataType: 'json',
                data: JSON.stringify(data),

                // beforeSend is invoked by jQuery, used to send a jqXHR object to get a request from $.aJax
                beforeSend: function (xhr)
                {
                    xhr.setRequestHeader("Authorization",
                        "Basic " + btoa(self.username + ":" + self.password));
                },
                // if $.aJax request comes back with an error such as invalid username
                error: function(jqXHR)
                {
                    console.log("ajax error " + jqXHR.status);
                }               
            };
            return $.ajax(request); // Returns value of the $.aJax request
        }

        self.add = function(task)
        {
            self.ajax(self.tasksURI, 'POST', task).done(function(data)
            {
                self.tasks.push
                ({
                    uri: ko.observable(data.task.uri),
                    title: ko.observable(data.task.title),
                    description: ko.observable(data.task.description),
                    done: ko.observable(data.task.done)
                });

            });
        }

    };
    window.viewModel = new TabViewModel();
    ko.applyBindings(window.viewModel, $('#tab')[0]);          
</script>

2 个答案:

答案 0 :(得分:0)

是的,您可以在单个控件上使用多个绑定,但您尝试执行的操作是在单个控件上使用多个SAME绑定。如果对控件使用相同类型的绑定,则会选择相同绑定的第二种用法。你可能不想这样做。

title中保存的值会更新为包含当前所选单选按钮的值属性值,即输入中的value="DevQ"value="Dev2"。这意味着$data.title 中存储的值正是您正在寻找的内容!即您需要的单选按钮。看看下面的代码片段。它希望它有助于为您解决问题。

&#13;
&#13;
ko.applyBindings({
  title: ko.observable('DevQ')
});
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<label>
  <input type="radio" value="DevQ" name="from" data-bind="checked: title" />DevQ</label>
<label>
  <input type="radio" value="Dev2" name="from" data-bind="checked: title" />Dev2</label>
<br/>
<hr/>
<br/>The value held in title() is updated to contain the value of the value attribute of the radio button that is selected
<br/>
<br/>
<b id="myRadioFrom" class="label">From: </b><span data-bind="text: $data.title"></span>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

You cannot have the same binding twice on one element, at least not with the built in bindings.

Instead, you should structure your view models in a way that each function has access to the relevant scope.

Typically, I tend to have a root or parent view model that wires up Ajax requests, and have smaller view models for domain concepts like a task. For example:

// Fake jQuery ajax stuff:
var $ = { ajax: function(options) { console.log(options); } };

function Task() {
  this.title = ko.observable("");
}

function RootVm() {
  var self = this;
  
  self.user = ko.observable("fake-username");
  self.password = ko.observable("sec!ret");
  
  self.tasks = ko.observableArray([new Task(), new Task()]);
  
  function doAjaxCall(task) {
    $.ajax({
      data: task.title(),
      user: self.user(),
      password: self.password()
    });
  }
  
  self.migrate = function(task) {
    doAjaxCall(task);
  };
}

ko.applyBindings(new RootVm());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>

<ul data-bind="foreach: tasks">
  <li>
    Title:
    <input data-bind="textInput: title">
    <button data-bind="click: $root.migrate">migrate</button>
  </li>
</ul>

<hr>

User: <input data-bind="textInput: user"><br>
Password: <input data-bind="textInput: password">