0

I am working on a webshop where a user can enter the amount of a desired product using an input field or incrementer buttons.

When i click on the incrementers "Minus" and "Plus" the value changes as expected and the input field is updated. However, when i enter a value into the input field it does not update the ng-model, the incrementers still work but the amount no longer updates the input.

After pressing on the addOrUpdateRelated button a console.log shows that $scope.Amount is still the original value after the input field was manually edited.

Here is a snippet of the HTML code:

<div ng-controller="CartActionController" ng-init="init('@baseUrl', product.ArticleDetailIds[0], '@configuration.DefaultNumberInAmount', product.MinimalSalesAmount, product.PackageAmount)"
                 style="display: flex;" class="@configuration.CSSClassAmount">
   <div class="col-lg-6" style="margin-top: 1.3rem;" ng-if="currentIndex == 0">
       <div>
            @if (configuration.AllowCartAnonymous || ViewBag.IsLoggedIn)
            {
               <div style="display: flex; flex-direction: column;">
                 <div class="section text-center ng-hide checkout" ng-show="CartActionControllerLoaded">
                    <div class="shoppingCheckout">
                         <div style="display: flex;">
                            <div class="btn-sm btn-default minus amount-button" ng-click="minus()"><i class="fa fa-minus"></i></div>
                            <input class="amount form-control" style="height: 30px;" ng-model="Amount" />
                            <div class="btn-sm btn-default plus amount-button" ng-click="plus()"><span class="fa fa-plus"></span></div>
                        </div>
                    </div>
                 </div>
               </div>
             }
       </div>
   </div> 
   <div class="col-lg-4 shoppingcart-subitem" ng-if="currentIndex > 0">
       <div style="display: flex;">
           @if (configuration.ShowAddToCartButtons && (configuration.AllowCartAnonymous || ViewBag.IsLoggedIn))
           {
              <div ng-show="Success" class="fade-in">
                 <div class="card-button text-white bg-success">
                     <div class="card-body">
                            @Product.Added
                     </div>
                  </div>
              </div>
              <div ng-show="Error">
                  <div class="card-button text-white bg-danger">
                     <div class="card-body">
                            {{Error}}
                     </div>
                  </div>
              </div>
              <div class="shoppingCheckoutButton" style="margin-bottom: 5px;">
                  <div class="section" ng-hide="Error || Success">
                       <button class="btn" ng-click="addOrUpdateRelated(product.PackageAmount)" style="padding: 0 10px;"><span class="fa fa-shopping-cart" aria-hidden="true"></span></button>
                  </div>
              </div>
           } 
        </div> 
    </div>
</div>

And here is a snippet of the controller code:

$scope.Amount = -1;
$scope.AmountVariant = -1;
$scope.ArticleDetailId = -1;
$scope.BaseUrl = "";
$scope.Success = false;
$scope.Error = "";
$scope.CartActionControllerLoaded = false;
$scope.DefaultNumberInAmount = 0;
$scope.MinimalSalesAmount = 0;
$scope.PackageAmount = 1;

$scope.init = function (baseurl, articleDetailId, amount, minimalSalesAmount, packageAmount) {
    $scope.BaseUrl = baseurl;
    $scope.ArticleDetailId = articleDetailId;
    $scope.Amount = amount;
    $scope.DefaultNumberInAmount = amount;
    $scope.Success = false;
    $scope.Error = "";
    $scope.CartActionControllerLoaded = true;
    $scope.MinimalSalesAmount = minimalSalesAmount;
    $scope.PackageAmount = packageAmount;
}

    $scope.addOrUpdateRelated = function (packageAmount, noErrorOnZero) {
    if (noErrorOnZero == undefined) {
        noErrorOnZero = false;
    }
    console.log($scope.Amount); // Amount stays 0 after the input has been changed directly, Amount changes when the incrementer buttons are used but it is no longer shown in the input field if the field was manually edited.
    $scope.Error = "";
    if ($scope.Amount != undefined && $scope.Amount > 0) {
        $http.get(
            $scope.BaseUrl + "API/Cart/Add?articleDetailId=" + $scope.ArticleDetailId + "&amount=" + $scope.Amount + "&packageAmount=" + packageAmount,
            {
                params: {}
            }).then(function (response) {
                $scope.$emit('UpdateCart', response.data);
                $scope.Amount = 0;
                $scope.Success = true;
            });
    } else if ($scope.Amount == 0 && noErrorOnZero) {
        $scope.Error = "";
        return;
    } else {
        $scope.Error = "Aantal heeft geen correcte waarde";
    }
}

  $scope.plus = function () {
    $scope.Amount++;
    //if ($scope.Amount <= 0) $scope.Amount = 1;
    $scope.Success = false;
    $scope.Error = "";
    $scope.Loaded = false;
}

$scope.minus = function () {
    $scope.Amount--;
    if ($scope.Amount <= 0) $scope.Amount = $scope.DefaultNumberInAmount;
    if ($scope.MinimalSalesAmount > 0) {
        $scope.Success = false;
        $scope.Error = "Van dit artikel moet u minimaal " + $scope.MinimalSalesAmount + " bestellen";
        $scope.Loaded = false;
    } else {
        $scope.Success = false;
        $scope.Error = "";
        $scope.Loaded = false;
    }
}

I'm assuming the input field is somehow not correctly bound to the value $scope.Amount, but i have no idea how to fix this problem nor the fact that the incrementers do not update the field after the input field was changed manually.

Any help would be greatly appreciated.

Kyllion
  • 1
  • 1
  • 2
  • This appears to be the well-known AngularJS dot problem. See "Common Mistake #2" here: https://www.toptal.com/angular-js/top-18-most-common-angularjs-developer-mistakes. Also see: https://stackoverflow.com/questions/18128323/if-you-are-not-using-a-dot-in-your-angularjs-models-you-are-doing-it-wrong – Jack A. May 21 '21 at 12:25
  • So if i understand the article and other question correctly, I should change $scope.Amount to $scope.Amount.CurrentAmount so it becomes a nested object. Then I should change the references of the other functions that use Amount in my code of $scope.Amount to $scope.Amount.CurrentAmount aswell, then the ng-model will correctly update and the functions get the correct value? – Kyllion May 21 '21 at 12:33
  • Yes, that's the basic idea. You should also look into using the "controller as" syntax, as that provides a standardized way to work around this issue. https://www.codementor.io/@cnorthfield/why-you-should-use-angularjs-s-controller-as-syntax-6i001lr5p – Jack A. May 21 '21 at 12:39
  • That has fixed it, I was going crazy trying to figure out the problem so thank you kindly. I'll have a look into the "controller as" syntax thank you for the tip. – Kyllion May 21 '21 at 12:58

0 Answers0