Javascript $parent.myFunction未在KnockoutJs中将行作为参数返回

Javascript $parent.myFunction未在KnockoutJs中将行作为参数返回,javascript,knockout.js,knockout-2.0,Javascript,Knockout.js,Knockout 2.0,我第一次使用knockoutjs,试图获得一个任务列表,然后能够单击其中一个以弹出形式显示它。我遇到的问题是data bind=“click:$parent.edit”,它调用ToDoListViewModel/edit 当我第一次开始编写列表代码时,它会将当前行的todo对象作为第一个参数传入edit函数。在为我的添加/编辑弹出窗体添加第二个视图模型后,它不再以这种方式工作。调用$parent.edit仍然调用edit函数,但是现在它传入一个空对象{} 看起来我遇到了一些相互冲突的绑定问题,有

我第一次使用knockoutjs,试图获得一个任务列表,然后能够单击其中一个以弹出形式显示它。我遇到的问题是data bind=“click:$parent.edit”,它调用ToDoListViewModel/edit

当我第一次开始编写列表代码时,它会将当前行的todo对象作为第一个参数传入edit函数。在为我的添加/编辑弹出窗体添加第二个视图模型后,它不再以这种方式工作。调用$parent.edit仍然调用edit函数,但是现在它传入一个空对象{}

看起来我遇到了一些相互冲突的绑定问题,有什么想法吗

以下是html的待办事项列表:

<table class="table table-striped table-hover" data-bind="visible: isVisible">
                <thead>
                    <tr>
                        <th>To-Do</th>
                        <th>Estimate</th>
                        <th>Deadline</th>
                        @if (Model == null) { <th>Property</th> }
                        <th>Tenant</th>
                        <th style="display: none;">Assigned To</th>
                        <th></th>
                    </tr>
                </thead>
                <tbody data-bind="foreach: todos">
                    <tr data-bind="visible: isVisible()">
                        <td><a class="pointer" title="Edit To-Do" data-bind="click: $parent.edit, text: Task"></a></td>
                        <td data-bind="text: FormattedAmount"></td>
                        <td data-bind="text: FormattedDueDate"></td>
                        <td data-bind="visible: $parent.showPropertyColumn, text: PropertyName"></td>
                        <td data-bind="text: TenantName"></td>
                        <td>
                            <div class="btn-group pull-right">
                                <a class="btn btn-primary pointer default-click-action" data-bind="click: $parent.markComplete">Mark Complete</a>
                                <button class="btn btn-primary dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></button>
                                <ul class="dropdown-menu">
                                    <li><a class="pointer" data-bind="click: $parent.edit">Edit To-Do</a></li>
                                    <li><a class="pointer" data-bind="click: $parent.remove">Delete To-Do</a></li>
                                </ul>
                            </div>
                        </td>
                    </tr>
                </tbody>
            </table>

一种可能的解决方案是更换:

data-bind="click: $parent.edit"


你不能把你的代码减少到最低限度来展示你的问题吗?可能在JSFIDLE>
function ToDoList () {

    if(!(this instanceof arguments.callee)) 
        return new arguments.callee();

    var parent = this;
    this.showCompleted = ko.observable(false);
    this.tenantFilter = new PropertyTenantFilter();
    this.viewModel = {
        list: new ToDoListViewModel(),
        form: new ToDoFormViewModel()
    };

    this.init = function () {
        //get all tenants.
        utils.block($("#grid-content"), "Loading");
        this.tenantFilter.init(function () {
            //initialize view model.
            ko.applyBindings(this.viewModel);
            //setup controls & events.
            $("#dueDate").datepicker();
            $("#listingId").change(this.tenantFilter.getByListing.bind(this.tenantFilter)).change();
        } .bind(this));
    };

    function ToDoListViewModel() {
        //init.
        var self = this;
        self.todos = ko.observableArray([]);

        //computed.
        self.showPropertyColumn = ko.computed(function () {
            return $("#originalListingId").val().length == 0;
        });
        self.isVisible = ko.computed(function () {
            return _.find(self.todos(), function (todo) { return todo.isVisible(); }) != null;
        });

        //operations.
        self.add = function () {
            //set form field values.
            parent.viewModel.form.fill(new schemas.ToDo({}, parent));
            //show popup.
            $("#popup").modal("show");
        };
        self.edit = function (todo) {
            console.debug("edit: " + JSON.stringify(todo));
            //set form field values.
            parent.viewModel.form.fill(todo);
            //update tenants dropdown for selected listing.
            parent.tenantFilter.getByListing();
            //show popup.
            $("#popup").modal("show");
        };
        self.markComplete = function (todo) {
            parent.markComplete(todo);
        };
        self.remove = function (todo) {
            var result = confirm("Are you sure that you want to delete this To-Do?");
            if (result) {
                //save changes.
                utils.ajax(basePath + "properties/deletetodo",
                    { id: todo.Id },
                    function (success) {
                        //refresh results.
                        self.todos.remove(todo);
                        //show result.
                        utils.showSuccess('The To-Do has been deleted successfully');
                    }
                );
            }
        };
        self.toggleShowCompleted = function () {
            parent.showCompleted(!parent.showCompleted());
            $("#showCompletedTodos").text(parent.showCompleted() ? "Show Active" : "Show Completed");
        };
        self.update = function (todo) {
            var existingToDo = _.find(self.todos(), function (item) { return item.Id() == todo.Id(); });
            existingToDo = todo;
        };

        //load todos from server.
        utils.ajax(basePath + "properties/gettodos",
            { id: $("#originalListingId").val(), showCompleted: parent.showCompleted() },
            function (results) {
                var mappedTodos = $.map(results, function (item) { return new schemas.ToDo(item, parent); });
                self.todos(mappedTodos);
                $("#grid-content").unblock();
            }
        );
    }

    function ToDoFormViewModel() {
        //init.
        var self = this;
        self.todo = ko.observable({});
        utils.setupPopupForm(self.saved);

        //operations.
        self.fill = function (todo, isEdit) {
            //set form field values.
            self.todo = todo;
            if (todo.Id()) {
                //update tenants dropdown for selected listing.
                parent.tenantFilter.getByListing();
            }
            //show popup.
            $("#popup").modal("show");
        };
        self.save = function (todo) {
            self.todo = todo;
            $("#form").submit();
        };
        self.saved = function (result) {
            var todo = new schemas.ToDo(result.todo, parent);
            if (result.isInsert)
                parent.viewModel.list.todos().push(todo);
            else
                parent.viewModel.list.update(todo);
            utils.showSuccess("Your To-Do has been saved successfully.");
        };
        self.markComplete = function (todo) {
            parent.markComplete(todo);
        };
    }

    this.markComplete = function (todo) {
        var result = confirm("Are you sure that you want to mark this To-Do complete?");
        if (result) {
            //save changes.
            utils.ajax(basePath + "properties/marktodocomplete", {
                    id: todo.Id()
                },
                function () {
                    todo.IsComplete(true);
                    //show success.
                    utils.showSuccess('Your To-Do has been marked completed');
                } .bind(this)
            );
        }
    }

    this.init();

}
data-bind="click: $parent.edit"
data-bind="click:$root.viewModel.list.edit"