jwgreg
jwgreg

Reputation: 133

UIBootstrap and Angularjs datepicker tabbing and direct entry

We are working on a SPA using Angularjs and Breeze based on the HotTowel template

We have multiple datePickers on the page that are giving us the following problems:

Essentially, this fine if the users are willing to pick up a mouse and click a date in the picker and never try to enter a date. That is not realistic for our user community.

Here is the html:

                                <label for="ApplicationCompleteDate" data-ng-show="vm.mode === 'edit'"><strong>Application Complete Date:</strong></label>
                            <div class="input-append" data-ng-show="vm.mode === 'edit'">
                                <span>
                                    <input name="ApplicationCompleteDate" type="text" class="form-control input-medium" tabindex="16" placeholder="{{vm.format}}"
                                           datepicker-popup="{{vm.format}}" close-text="Close" show-weeks='false'
                                           is-open="vm.applicationCompleteDateOpened"
                                           datepicker-options="vm.dateOptions"
                                           data-ng-model="vm.formData.dateApplicationComplete"
                                           data-ng-required="vm.applicationCompleteDateRequired"
                                           data-ng-readonly="(!user.isInUserGroup && vm.mode === 'new') || (!user.isInCPUGroup && vm.mode === 'edit')" />
                                </span>
                                <span class="add-on">
                                    <a href="#" data-ng-click="vm.applicationCompleteDateOpen($event)"><i class="icon-calendar"></i></a>
                                </span>
                            </div>
                            <label for="DecisionDatePicker" data-ng-show="vm.mode === 'edit'"><strong>Decision Date:</strong></label>
                            <div class="input-append" data-ng-show="vm.mode === 'edit'">
                                <span>
                                    <input name="DecisionDatePicker" id="ddpID" type="text" class="form-control input-medium" tabindex="14" placeholder="{{vm.format}}"
                                           datepicker-popup="{{vm.format}}" close-text="Close" show-weeks='false'
                                           is-open="vm.decisionDateOpened"
                                           datepicker-options="vm.dateOptions"
                                           data-ng-model="vm.formData.dateDecision"
                                           data-ng-required="vm.decisionDateRequired"
                                           data-ng-readonly="(!user.isInUserGroup && vm.mode === 'new') || (!user.isInCPUGroup && vm.mode === 'edit')" />
                                </span>                                    
                                <span class="add-on">
                                    <a href="#" data-ng-click="vm.decisionDateOpen($event)"><i class="icon-calendar"></i></a>
                                </span>
                            </div>
                            <label for="DateClosedPicker" data-ng-show="vm.mode === 'edit'"><strong>Closed Date:</strong></label>
                            <div class="input-append" data-ng-show="vm.mode === 'edit'">
                                <span>
                                    <input name="DateClosedPicker" type="text" class="form-control input-medium" tabindex="15" placeholder="{{vm.format}}"
                                           datepicker-popup="{{vm.format}}" close-text="Close" show-weeks='false'
                                           is-open="vm.dateClosedOpened"
                                           datepicker-options="vm.dateOptions"
                                           data-ng-model="vm.formData.dateClosed"
                                           data-ng-required="false"
                                           data-ng-readonly="(!user.isInUserGroup && vm.mode === 'new') || (!user.isInCPUGroup && vm.mode === 'edit')" />
                                </span>                                    
                                <span class="add-on">
                                    <a href="#" data-ng-click="vm.dateClosedOpen($event)"><i class="icon-calendar"></i></a>
                                </span>
                            </div>

We are using two-way binding with ng-model.

Any help would be appreciated.

Thanks

Upvotes: 5

Views: 1852

Answers (3)

Brandon Johnson
Brandon Johnson

Reputation: 327

I ran into the same problem and solved it by creating a locally scoped placeholder variable on the view model for binding to the date picker.

<input type="text"
    class="form-control"
    datepicker-popup="M/d/yyyy"
    is-open="vm.openedStartDate"
    ng-model="vm.selectedStartDate"
    close-text="Close"
    show-button-bar="false" />

This allows for the desired behavior of the datepicker.

I then set the breeze entity value to this local variable just before saving the changes:

 task.StartDate = vm.selectedStartDate;
 task.EndDate = vm.selectedEndDate;
 datacontext.saveChanges();

It's not perfect, but it is a viable workaround for the problem you are describing.

Upvotes: 0

Ward
Ward

Reputation: 17863

I need a repro to work on if you want me to look into this. Something in plunker would be nice.

I do not think we can change our property test. We went to that much trouble for a good reason. Angular doesn't have any notion of DataType so it can't do what we do.

But we should be able to arrive at a suitable solution, perhaps involving Angular. For example, you could write a trivial directive for this. You may be able to handle it with existing Ng; I vaguely recall that you can specify a binding parser that can duplicate the breeze logic. It's been too long since I looked at that but I think it's there.

Upvotes: 0

Bruno Altinet
Bruno Altinet

Reputation: 286

Had the same problem and i found the problematic code: it's line 4786 in breeze.debug.js

    // exit if no change - extra cruft is because dateTimes don't compare cleanly.
if (newValue === oldValue || (dataType && dataType.isDate && newValue && oldValue && newValue.valueOf() === oldValue.valueOf())) {
    return;
}

Problem is that angulars dirty checker is doing just === so in the end it overwrites the view value because it's not the same as in the model (because breeze skips the update). if you omit the part after || you can enter values normally, altough i then ran into a different set of problems.

This is a mismatch between angular's way of looking at data and breeze. I hope Ward sees this. I'll pull up a ticket. Not sure what would be a good place to handle it, but i think breeze would be the one (because angular works fine with pojos). I would update the reference without the sideffects of the update itself.

Upvotes: 2

Related Questions