admin管理员组

文章数量:1418361

I have this piece of html code in my application (the ng-app and ng-controller values are defined before):

<div>
    <label for="projectSearchDateFrom"><%= Res("Projects.Search.From")%></label>
    <input id="projectSearchDateFrom" type="text" ng-model="startDate" ui-date="dateOptions"/>
    <img ng-show="hasStartDate()" ng-click="clearStartDate()" src="/_Layouts/ClientPortal/Images/layout/TA/delete-small.png" alt="<%= Res("ToolbarDialog.Clear")%> <%= Res("Projects.Search.From")%>" title="<%= Res("ToolbarDialog.Clear")%>" />
</div>

My AngularJS controller looks like this:

function ProjectSearchCtrl($scope) {
    $scope.startDate = '';

    $scope.hasStartDate = function () {
        return $scope.startDate != '';
    };

    $scope.clearStartDate = function () {
        $scope.startDate = '';
    };

    $scope.dateOptions = {
        dateFormat: "yy-mm-dd",
        showOn: "focus"
    };
}

This works perfectly: I have a datepicker set up correctly thanks to AngularUI, the AngularJS binding works...

But if I change the showOn value to "button" or "both" (the two possible options which will actually show the datepicker button), everything after the input (containing the ui-date attribute) stops working: ng-show, ng-click... The controller doesn't even get called.

Versions (all is up-to-date):

  • jQuery 1.7.2
  • angularJS 1.0.0
  • angularUI 0.1.0
  • Chrome 20

I have this piece of html code in my application (the ng-app and ng-controller values are defined before):

<div>
    <label for="projectSearchDateFrom"><%= Res("Projects.Search.From")%></label>
    <input id="projectSearchDateFrom" type="text" ng-model="startDate" ui-date="dateOptions"/>
    <img ng-show="hasStartDate()" ng-click="clearStartDate()" src="/_Layouts/ClientPortal/Images/layout/TA/delete-small.png" alt="<%= Res("ToolbarDialog.Clear")%> <%= Res("Projects.Search.From")%>" title="<%= Res("ToolbarDialog.Clear")%>" />
</div>

My AngularJS controller looks like this:

function ProjectSearchCtrl($scope) {
    $scope.startDate = '';

    $scope.hasStartDate = function () {
        return $scope.startDate != '';
    };

    $scope.clearStartDate = function () {
        $scope.startDate = '';
    };

    $scope.dateOptions = {
        dateFormat: "yy-mm-dd",
        showOn: "focus"
    };
}

This works perfectly: I have a datepicker set up correctly thanks to AngularUI, the AngularJS binding works...

But if I change the showOn value to "button" or "both" (the two possible options which will actually show the datepicker button), everything after the input (containing the ui-date attribute) stops working: ng-show, ng-click... The controller doesn't even get called.

Versions (all is up-to-date):

  • jQuery 1.7.2
  • angularJS 1.0.0
  • angularUI 0.1.0
  • Chrome 20
Share Improve this question edited Jul 23, 2012 at 11:58 Evren Kuzucuoglu asked Jul 23, 2012 at 11:30 Evren KuzucuogluEvren Kuzucuoglu 3,9051 gold badge31 silver badges53 bronze badges 2
  • 1 I suspect that this is because the jquery date picker widget is messing with the HTML and confusing AngularJS. I'll have a think about what we can do. It might be that we have to wrap the date picker in a div or something to isolate changes that the jquery widget makes from affecting the rest of the HTML. – Pete BD Commented Jul 23, 2012 at 13:06
  • Well yes indeed, that workaround does the trick – Evren Kuzucuoglu Commented Jul 23, 2012 at 14:26
Add a ment  | 

3 Answers 3

Reset to default 6

Please take a look at this line in the Select2 directive. This is a note to ANYONE writing a directive / implementing a plugin in AngularJS (not just AngularUI):

Any plugin that injects a new DOM element immediately after the linked element runs the risk of disrupting the piler. The reason is because the way AngularJS works, it caches the index of each DOM element at pile time, and then makes a second pass upon linking. When you inject new DOM, you offset the index of all siblings immediately after the directive.

For this reason, I've been forced to wrap both TinyMCE and Select2 in a setTimeout so that the DOM is injected after the linking is done. Note that I don't bother using $timeout because I really don't need/want $apply() to fire just to turn on the plugin, as there are already callbacks in place that do this when the plugin changes the data.

I'll look into making sure this is uniform across AngularUI. Unfortunately, there appears to be no elegant solution to this problem in AngularJS at this time, however it's a problem I've been thinking about for some time and am constantly looking for a better solution towards.

Read this Google Groups post for more information about piling vs linking: https://groups.google./forum/?fromgroups#!searchin/angular/pile$20link/angular/RuWn5W3Q5I0/KJhcQJ_RNsIJ

You can also open a bug ticket on the AngularUI project in the future.

As suggested by Pete BD in his ment on the question, there is some kind of bug/unwanted behaviour in the way that jQueryUI and angularJS interact. A workaround is to wrap the input control in a div.

<div class="date">
    <label for="projectSearchDateFrom"><%= Res("Projects.Search.From")%></label>
    <div>
        <input id="projectSearchDateFrom" type="text" ng-model="startDate" ui-date="dateOptions"/>                                  
    </div>
    <img class="clear" ng-show="hasStartDate()" ng-click="clearStartDate()" src="/_Layouts/ClientPortal/Images/layout/TA/delete-small.png" alt="<%= Res("ToolbarDialog.Clear")%> <%= Res("Projects.Search.From")%>" title="<%= Res("ToolbarDialog.Clear")%>" />
</div>

Now I can use showOn "both" or "button".

This is fixed in the latest release!

本文标签: javascriptangularui datepicker seems to hang angularjs when showing buttonStack Overflow