JQuery doesn't locate DOM elements when using Durandal's compose

浪尽此生 提交于 2019-12-12 07:39:05

问题


I've recently ported my company's project to Durandal using Knockout and JQuery. Straight to the problem: I need to initialize JQuery UI's datepicker using two HTML inputs. JQuery, however, is unable to locate the inputs when I do this:

view:

<div data-bind="if: !CurrentUser()">
    <h1 data-bind="html: DisplayName"></h1>

    <div data-bind="compose: 'users/_UsersList.html'"></div>
</div>

<div data-bind="with: CurrentUser(), visible: CurrentUser()">
    <h1>User detail</h1>

    <div data-bind="compose: 'users/_UserDetail.html'"></div>
</div>

viewmodel - SelectUser() function is called when a user is selected in the first div, then the second div and also users/_UserDetail.html is loaded:

users.SelectUser = function (user) {
    users.CurrentUser(user);

    /* ... */

    $(function () {
        $("#datepickerFrom").datetimepicker({
            dateFormat: "d. m. yy",
            timeFormat: "HH:mm:ss",
            defaultDate: null
        });

        $("#datepickerTo").datetimepicker({
            dateFormat: "d. m. yy",
            timeFormat: "HH:mm:ss"
        });
    });
}

The important part of _UserDetail.html

<div class="control-group">
    <label class="control-label">Active from</label>
    <div class="controls">
        <input type="text" data-bind="value: ActiveFrom" id="datepickerFrom" />
    </div>
</div>
<div class="control-group">
    <label class="control-label">Active to</label>
    <div class="controls">
        <input type="text" data-bind="value: ActiveTo" id="datepickerTo" />
    </div>
</div>

Then the two HTML inputs come as undefined. If I change the div with the compose binding to the actual users/_UserDetail.html content, it works just fine, but then the view quickly becomes a mess - the html file isn't exactly small. If someone could point me to the right direction, I would be grateful. Thanks!


回答1:


In this scenario you need a Knockout Binding Handler.

In some scenarios the binding handlers can have issues with the Composition lifecycle, if thats the case and you are using Durandal 2 you can use the method composition.addBindingHandler. Otherwise just use ko.bindingHandlers.

You will need to create the bindings in the shell.js or main.js so they are available in all the application. Use the following code:

 var composition = require('durandal/composition');
 composition.addBindingHandler('datetimepicker', {
            init: function (element, valueAccessor) {
                var activeTo =  valueAccessor();  //What do you want to do with this value?
                $(element).datetimepicker({
                   dateFormat: "d. m. yy",
                   timeFormat: "HH:mm:ss",
                   defaultDate: null   //Maybe use activeTo here?
                  });
            }
         });

And in your UI:

 <input type="text" data-bind="datetimepicker: ActiveTo" id="datepickerTo" />

NOTE:

This code might not work, but you should definitely use this approach to create this kind of controls and use Durandal's composition lifecycle.




回答2:


Pretty sure the problem is with this:

users.SelectUser = function (user) {
    servers.CurrentUser(user);

    /* ... */

    $(function () {
        $("#datepickerFrom").datetimepicker({
            dateFormat: "d. m. yy",
            timeFormat: "HH:mm:ss",
            defaultDate: null
        });

        $("#datepickerTo").datetimepicker({
            dateFormat: "d. m. yy",
            timeFormat: "HH:mm:ss"
        });
    });
}

You have your jQuery datepicker init code inside a function. That means that it will only run when the SelectUser function gets called. Try moving that outside of any functions.



来源:https://stackoverflow.com/questions/18701228/jquery-doesnt-locate-dom-elements-when-using-durandals-compose

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!