使用 ng-change 更新 AngularJS 模型会导致一个字段在更新时变为空

Updating AngularJS model with ng-change causes one field to become null when updating

在 3 个单独的字段上同时更新 AngularJS 模型值会导致一个字段在 ng-change 上变为空。

我在使用 ng-change 时遇到了一些奇怪的行为。我拥有的是 3 个独立的领域,它们都集成在一起。一个是基本贷款金额,一个是 属性 的估计值,最后一个是贷款价值比。当输入基本贷款金额和估计值的值时,将计算贷款价值比率。然后,如果用户决定更改贷款与价值比率,则重新计算基本贷款金额 and/or 估计值,依此类推。

到目前为止,我的逻辑符合预期。我输入一个基本贷款金额,然后输入一个估计值,然后计算出贷款价值比。但是,一旦计算出该值,基本贷款金额字段就会清空并变为空。

我不确定为什么会这样,我尝试了 ng-blur 和 ng-change,但得到了相同的结果。我已经在 Chrome 中调试了几个小时。

我已经提供了我正在使用的 html 以及我控制器中的操作逻辑。

谢谢

这里是Plunker with my code

HTML内容

<div class="form-content">
    <form name="priceSearch" novalidate>
        <!-- Row 1 -->
        <div class="form-row">
            <!-- The LTV (Loan-To-Value) ratio is calculated as the amount of the mortgage lien divided by the appraised value of the property, expressed as a percentage. -->
            <div class="form-group col-md-3">
                <!--if user enters loan amount, update LTV-->
                <label for="baseLoanAmt">Base Loan Amount</label>
                <input name="baseLoanAmt" class="form-control form-control-sm" type="number" placeholder="0.00" ng-step="any" ng-model="pricer.baseLoanAmount" ng-required="true" aria-describedby="blaHelpInline" ng-change="updateBaseLoanAmtEstValLTV('baseLoanAmt', pricer.baseLoanAmount)" ng-model-options="{debounce: {default: 400, blur: 0}}">
            </div>
            <div class="form-group col-md-3">
                <label for="estimatedVal">Estimated Value</label>
                <input name="estimatedVal" class="form-control form-control-sm" type="number" placeholder="0.00" step="any" ng-model="pricer.appraisedEstimatedValue" ng-required="true" aria-describedby="estValHelpInline" ng-change="updateBaseLoanAmtEstValLTV('estimatedVal', pricer.appraisedEstimatedValue)" ng-model-options="{debounce: {default: 400, blur: 0}}">
            </div>
            <div class="form-group col-md-3">
                <!--if user enters LTV, update base loan amount-->
                <label for="ltvRatio">LTV</label>
                <input name="ltvRatio" class="form-control form-control-sm" type="number" ng-step="any" ng-model="pricer.ltvRatio" ng-change="updateBaseLoanAmtEstValLTV('ltvRatio', pricer.ltvRatio)" ng-model-options="{debounce: {default: 400, blur: 0}}" ng-pattern="/^\d+(\.\d{1,2})?$/">
            </div>
            <div class="form-group col-md-3">
                <label>Loan Purpose</label>
                <select class="form-control form-control-sm" ng-model="pricer.loanInformation.loanPurpose" ng-options="obj.val as obj.key for obj in loanPurposeOptions" ng-required="true">
                </select>
            </div>
        </div>
        <!-- End Row 1 -->
    </form>
</div>

控制器逻辑

app.controller('pricingSearch', ["$scope", "$rootScope", "$q", "dal", "$http", "$timeout", "$filter", function ($scope, $root, $q, _dal, $http, $timeout, $filter) {

    // Precision Round function
    function precisionRound(number, precision) {
        var factor = Math.pow(10, precision);
        return Math.round(number * factor) / factor;
    }

    $scope.pricer = {
        "baseLoanAmount": 0,
        "appraisedEstimatedValue": 0,
        "ltvRatio": 0,
        "fico": 700,
        "debtToIncomeRatio": 15.0,
        "waiveEscrows": false,
        "loanType": "Conforming",
        "loanTerms": {
            "ThirtyYear": true
        }
    };

    $scope.updateBaseLoanAmtEstValLTV = function (fieldName, value) {
        var findBaseLoanAmtRatio = ($scope.pricer.appraisedEstimatedValue * $scope.pricer.ltvRatio) /10;
        var findEstimatedValRatio = ($scope.pricer.baseLoanAmount * $scope.pricer.ltvRatio) / 10;
        var findLtvRatio = ($scope.pricer.baseLoanAmount / $scope.pricer.appraisedEstimatedValue) * 10;

        console.log('The fieldName is: ' + (fieldName));
        console.log('The value is: ' + (value));

        if (fieldName !== 'baseLoanAmt' && value != null) {
            console.log('Fire 1');
            $scope.pricer.baseLoanAmount = precisionRound(findBaseLoanAmtRatio, 2);
        }
        if (fieldName !== 'estimatedVal' && value != null) {
            console.log('Fire 2');
            $scope.pricer.appraisedEstimatedValue = precisionRound(findEstimatedValRatio, 2);
        }
        if (fieldName !== 'ltvRatio' && value != null) {
            console.log('Fire 3');
            $scope.pricer.ltvRatio = precisionRound(findLtvRatio, 3);
        }
    };
}]);

https://plnkr.co/edit/BFlvshCp1Rhs6WpxrjmN?p=preview

这可能是因为在您的代码中的某些地方您除以零。 除非您首先检查它不是零,否则永远不要除以它。

function calcLtv() {
  var findLtvRatio;
    if($scope.pricer.appraisedEstimatedValue === 0) {
      findLtvRatio = 0;
    }
    else {
      findLtvRatio = ($scope.pricer.baseLoanAmount / $scope.pricer.appraisedEstimatedValue) * 10;
    }
    return findLtvRatio;
}

好的,我已经解决了我遇到的问题。首先,我必须设置一个系统来告诉 angular 计算正在进行,然后计算停止。

然后我对字段值做了一些额外的检查,确保它们没有被零除。我还添加了一些时间来完成计算,这样它们就不会完成得太快。

感谢 Pop-A-Stash 指出对我来说显而易见的事情。

可以在 this plunkr

找到更新的源
var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope, $timeout) {

// Precision Round function
function precisionRound(number, precision) {
    var factor = Math.pow(10, precision);
    return Math.round(number * factor) / factor;
}

$scope.pricer = {
    "baseLoanAmount": 0,
    "appraisedEstimatedValue": 0,
    "ltvRatio": 0
};

$scope.recalculateLoanVals = function(fieldName, value) {

    var findBaseLoanAmtRatio = $scope.pricer.appraisedEstimatedValue * $scope.pricer.ltvRatio;
    var findEstimatedValRatio = $scope.pricer.baseLoanAmount * $scope.pricer.ltvRatio;
    var findLtvRatio = $scope.pricer.baseLoanAmount / $scope.pricer.appraisedEstimatedValue;

    if ($scope.calculating) {
        // console.log('Calculating...');
        // console.log('The field name is: ', fieldName);
        // console.log('The value is: ', value);

        if (($scope.pricer.baseLoanAmount > 0) && ($scope.pricer.appraisedEstimatedValue > 0) && (fieldName !== 'ltvRatio')) {
            // console.log('Just baseLoanAmt and estimatedVal are not equal to zero');
            // console.log('Calculating is: ', $scope.calculating);
            $timeout(function() {
                $scope.pricer.ltvRatio = precisionRound(findLtvRatio, 2);
            }, 1000);
        }

        if (($scope.pricer.baseLoanAmount > 0) && ($scope.pricer.appraisedEstimatedValue > 0) && ($scope.pricer.ltvRatio > 0) && fieldName !== 'baseLoanAmt') {
            // console.log('All three are not equal to zero');
            $scope.pricer.ltvRatio = value;
            $timeout(function() {
                $scope.pricer.baseLoanAmount = precisionRound(findBaseLoanAmtRatio, 0);
            }, 1000);
        }

        return;
    }
    $scope.calculating = true;

    $timeout(function() {
        // console.log('No longer calculating!');
        $scope.calculating = false;
    }, 1200);
};
});