javascripthtmlangularjswebix

AngularJS - How to prevent input values from undesirably clearing on ng-click button press


I have an issue which I believe is related to a $digest / $apply happening in my application causing the inputs to clear when I press the "+" button in a particular row of my inputs.

How do I properly prevent input values from clearing on ng-click button press?

<tr ng-repeat="event in [0,1,2,3,4,5]">
    <td>
        <div class="evt{{event}}" enabled="{{ctrl.enabledItem[event]}}"
             ng-show="ctrl.config.cost{{event}}.done" config="cost{{event}}"
             webix-ui="cost{{event}}" width="30" height="30"
             type="text" id="cost{{event}}" name="cost[{{event}}]">
        </div>
    </td>
    <td>
        <input type="button" id="evt{{event}}" ng-if="event != 5" 
               style="display:none" ng-click="ctrl.enable(event)"
               value="+">
    </td>
</tr>

Sample screenshot before button click (with inputs filled out completely)

enter image description here

Please see http://projectaim.ddns.net/#!/risk/edit/1

See http://jsfiddle.net/02Lv1s9d for an MCVE (minimal complete verifyable example)

First row of target table must be completely filled out for + button to appear and + button must be clicked to trigger the problem.


Solution

  • You guessed it right, it's an angularJS digest issue. You have a $element.ready event in webix-ui directive which does not call $scope.$digest() at the end, so changes within this event handler is not digested when the page loads and elements are rendered.

    The digest cycle runs when you click the plus button for the first time re-rendering your UI. To solve this just add $scope.$digest() at the end of the event handler.

    $element.ready(function() {
        // Here goes all existing code
        // Add the following block to enable the row
        let rowIndex = dataname[dataname.length - 1];
        $scope.$watch(() => $scope.$parent.enabledItem[rowIndex], isEnabled => {
            $scope.config[dataname].disabled = !isEnabled;
            watcher();
        });
        // call digest at the end
        $scope.$digest();
    });
    

    N.B: There are some places you are using native JavaScript setTimeout, use $timeout instead which takes care of digest cycles.

    Update:

    To enable next row you have to add the watcher as I did above, and change click event binding.

    <input type="button" ng-click="enable(event)">
    

    to

    <input type="button" ng-click="enable(event + 1)">