5
votes

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:

  • When the user tabs into a datepicker the datepicker opens but will not close when the user tabs to the next control. Since the datepickers are stacked in the same column of the ui, this causes the dropdown to cover the fields below. The only way to clear them is to select a date or click elsewhere on the form

  • The user cannot key a date into the input area when editing an existing record that is bound to the data model. If they highlight the date and try to enter it, it erases the existing date and will not allow the user key a new one. If they click the X to clear the input field, they cannot key a new date. If they position their cursor at the end of the date, and backspace, the date disappears and the calendar picker is set to January of 1902.

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

3
The same thing bothers me too. Ever solved this problem?zszep
We have been busy on other issues and have not found a good solution yet. However, we will be getting back to that in the next couple of weeks. When a solution is found, I will post it here. We are pretty sure it is a result of 2 way binding.jwgreg
Right now, I am researching too. I think that I am on the right path, so as soon I have something, I'll post too.zszep
Did you guys ever find a solution to this?sharpmachine

3 Answers

2
votes

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.

0
votes

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.

0
votes

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.