0

オートコンプリートを使用して、テーブル行の動的リストに名前を追加しています。新しい名前を追加すると、新しい行が作成されますが、searchText と searchId は更新されません。リンクの削除は機能しているようです。だから私の見解は次のようになります。

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<SHP.Models.TrainingListEmployeesViewModel>" %>
<%@ Import Namespace="System.Web.Script.Serialization" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Bulk Training
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<form class="employeeListEditor">
    <h3>Allocate or cancel training for the selected employees</h3>
    <table>
        <tr>
            <td style="text-align: right;">Course Name</td>
            <td><%: Html.EditorFor(model => model.TrainingName) %></td>
        </tr>
        <tr>
            <td style="text-align: right;">Description (optional)</td>
            <td><%: Html.TextAreaFor(
               model => model.TrainingDescription, new { maxlength = "255", style = "width:400px;height:100px;" }) %></td>
        </tr>
    </table>
    <%: Html.EditorFor(model => model.ClientEmployeeSelector) %>
    <button data-bind="click: addEmployee">Add</button>
    <%--<input type="hidden" name="numberOfEmployees" id="numberOfEmployees" value="<%:Model.EmployeeList.Count %>" />--%>
    <div id="displayEmployees" style="margin-top:10px;display: block">
        <table id="employeeDataTable" class="groupBorder">
            <thead>
                <tr>
                    <th></th>
                    <th>Employee</th>
                </tr>
            </thead>
            <tbody data-bind="foreach: employees">
                <tr>
                    <td>
                        <a href="#" data-bind="click: $parent.removeEmployee">Remove</a>
                        <input type="hidden" data-bind="value: searchId"/>
                    </td>
                    <td><span data-bind="text: searchText"></span></td>
                </tr>               
            </tbody>
        </table>
    </div>
</form>

    <script type="text/javascript">
        function Employee(id, text) {
            var self = this;
            self.searchId = id;
            self.searchText = text;
        }

        var initialData = <%= new JavaScriptSerializer().Serialize(Model) %>;
        function ViewModel() {
            var self = this;
            self.employees = ko.observableArray(initialData.EmployeeList);
            self.searchText = ko.observable(initialData.SearchText);
            self.searchId = ko.observable(initialData.SearchTextId);
            self.removeEmployee = function(employee) {
                self.employees.remove(employee);
            };
            self.addEmployee = function() {
                self.employees.push(new Employee(self.searchId, self.searchText));
                $('#SearchText').val('');
            };
            self.save = function() {
                ko.utils.postJson(location.href, { employees: self.employees });
            };
        }
        ko.applyBindings(new ViewModel());
    </script>
</asp:Content>

そして、追加ボタンをクリックすると(追加イベントがリターンキーによってトリガーされるように、機能しているときに削除することをお勧めします)、次の行がテーブルに追加されます。

<tbody data-bind="foreach: employees">
                <tr>
                    <td>
                        <a href="#" data-bind="click: $parent.removeEmployee">Remove</a>
                        <input type="hidden" data-bind="value: searchId" value=""/>
                    </td>
                    <td><span data-bind="text: searchText"/></td>
                </tr>               
            </tbody>

そのため、正しい削除リンクが表示され、同様に機能します。ただし、searchId と searchText の両方が設定されていません。私は何を間違っていますか?

4

3 に答える 3

2

コードが を呼び出すときnew Employee(self.searchId, self.searchText)、2 つのオブザーバブルを引数として渡します。つまり、値ではなく、オブザーバブル自体を渡します。したがって、新しい Employee のプロパティは、主な 2 つのオブザーバブルへの参照になります。これはおそらくあなたが望むものではありません。

次のように、(オブザーバブル自体ではなく) オブザーバブルのを渡す必要がありますnew Employee(self.searchId(), self.searchText())。このようにして、各新入社員は 2 つの主な監視対象の現在の値のコピーを取得します。

また、多くの場合、従業員のプロパティ自体を監視可能にすることは便利です (たとえば、変更できる場合)。

ここにそれを示すフィドルがあります:http://jsfiddle.net/antishok/KXhem/73/

編集:ポスターのコメントに基づいて更新されたフィドルと詳細情報:http: //jsfiddle.net/antishok/KXhem/74/

于 2012-10-15T16:41:38.007 に答える
0

これが最良の答えかどうかはわかりませんが、途中で私を助けてくれたアンチショックに感謝します. 実際の JSON データは次のように保存されました。

{"EmployeeList":[],"ClientEmployeeSelector":{"SearchText":null,"SearchTextId":0},"Cvm":null,"TrainingName":null,"TrainingDescription":null};

そのため、SearchText と SearchTextId は ClientEmployeeSelector にネストされていました。もう 1 つの問題は、これらのフィールドのオブザーバブルがゼロと null として正しく設定されていたにもかかわらず、オートコンプリートから変更されたときに更新されなかったことです。それで、私がそれを修正した方法は次のとおりです。function Employee(id, text) { var self = this; self.searchId = id.val(); self.searchText = text.val(); }

    var initialData = <%= new JavaScriptSerializer().Serialize(Model) %>;
    function ViewModel() {
        var self = this;
        self.employees = ko.observableArray(initialData.EmployeeList);
        self.searchText = ko.observable($('#SearchText'));
        self.searchId = ko.observable($('#SearchTextId'));
        self.removeEmployee = function(employee) {
            self.employees.remove(employee);
        };
        self.addEmployee = function() {
            self.employees.push(new Employee(self.searchId(), self.searchText()));
            $('#SearchText').val('');
        };
        self.save = function() {
            ko.utils.postJson(location.href, { employees: self.employees });
        };
    }
    ko.applyBindings(new ViewModel());
</script>

これが最良の答えかどうかはわかりませんが、私が知る限り、うまくいきます。

于 2012-10-16T07:09:43.130 に答える
0

OK、これは私の最初の回答に対するアンチショックの有効な批判を考慮して、私の2番目の回答です。私が抱えていた問題は、変数 initialData をモデルに設定したことでした。ただし、オートコンプリート フィールドはモデルにありませんでした。これが私のスクリプトでの私の解決策です。

<script type="text/javascript">
    function Employee(id, text) {
        var self = this;
        self.searchTextId = ko.observable(id);
        self.searchText = ko.observable(text);
    }
    $(document).ready(function () {
        $('#SearchText').attr("data-bind", "value: autocompleteSearchText");
        $('#SearchTextId').attr("data-bind", "value: autocompleteSearchTextId");

        var initialData = <%= new JavaScriptSerializer().Serialize(Model) %>;
        var autocompleteData = { "autocompleteSearchTextId": 0, "autocompleteSearchText": null };
        function ViewModel() {
            var self = this;
            self.employees = ko.observableArray(initialData.EmployeeList);
            self.autocompleteSearchText = ko.observable(autocompleteData.autocompleteSearchText);
            self.autocompleteSearchTextId = ko.observable(autocompleteData.autocompleteSearchTextId);
            self.removeEmployee = function(employee) {
                self.employees.remove(employee);
            };
            self.addEmployee = function() {
                self.employees.push(new Employee(self.autocompleteSearchTextId(), self.autocompleteSearchText()));
                self.autocompleteSearchText('');
            };
            self.save = function() {
                var trainingName = $("#TrainingName").val();
                var trainingDescription = $("#TrainingDescription").val();
                ko.utils.postJson(location.href, { employees: self.employees, trainingName: trainingName, trainingDescription: trainingDescription });
            };
        }   
        ko.applyBindings(new ViewModel());
    });
</script>

JQuery を使用してデータバインディングをオートコンプリート フィールドに挿入すると、オブザーバブルが正常に機能します。私はこれを行うことから多くのことを学びました - おそらくこれはまだ最善の解決策ではありませんか? しかし、アンチショックに感謝します。

于 2012-10-17T08:22:15.227 に答える