角度:当输入更改时更新视图 + .this/$scope

angular: updating view when input changes + .this/$scope

本文关键字:新视图 this scope 更新 输入 角度      更新时间:2023-09-26

我有几个问题似乎想不通。我试图做一个小提琴来显示我的问题 https://jsfiddle.net/6dfyx2og/1/#&togetherjs=KxPTHsH0Pu,但我似乎无法让它工作,尽管它在我的应用程序中工作。值显示在屏幕上,可由输入框操作。但是现在,如果用户更改值,$scope.booking.nights将不会更新。(在我的应用程序中,当用户填写到达日期和离开日期时,它会调用函数calNights,为我们提供夜晚数)。

任何人都可以看到我的错误吗?

由于我无法让小提琴工作,我将在此处发布代码

控制器:

angular.module('squawsomeApp')
  .controller('BookingCtrl', function($scope){
    $scope.values = [1,2,3,4,5];
    // var self = this;
    function parseDate(str) {
      var mdy = str.split('/')
      return new Date(mdy[2], mdy[0]-1, mdy[1]);
    }
    function daydiff(first, second) {
      return (second-first)/(1000*60*60*24);
    }
    var calCheckIn = new Pikaday({
        field: document.getElementById('checkin'),
        format: 'MM/DD/YYYY',
        onSelect: function() {
          $scope.booking.checkin = null;
          $scope.booking.checkin = this.toString('MM/DD/YYYY');
          calNights();
        }
    });
    var calCheckOut = new Pikaday({
        field: document.getElementById('checkout'),
        minDate: $scope.checkin,
        format: 'DD/MM/YYYY',
        onSelect: function() {
          $scope.booking.checkout = this.toString('MM/DD/YYYY');
          calNights();
        }
    });
    var calNights = function(){
      console.log('outside')
      $scope.booking.nights = null;
      console.log($scope.booking.nights)
      if ($scope.booking.checkin && $scope.booking.checkout) {
        console.log('inside')
        $scope.booking.nights = daydiff(parseDate($scope.booking.checkin), parseDate($scope.booking.checkout));
        // return daydiff(parseDate(self.booking.checkin), parseDate(self.booking.checkout))
        console.log($scope.booking.nights)
      }
    };
    var calCost = function(){
      if ($scope.booking.nights < 7) {
        $scope.booking.cost = 145;
      } else if ($scope.booking.nights >= 7 && $scope.booking.nights <= 29){
        $scope.cost = 135;
      } else if ($scope.booking.nights >= 29){
        $scope.booking.cost = 120;
      }
    };
    $scope.booking = {
      checkin: null,
      checkout: null,
      guests: null,
      nights: null, //daydiff(parseDate(self.booking.checkin), parseDate(self.booking.checkout))
      cost: null,
      pretotal: this.nights * this.cost,
      tax: 0,
      total: this.pretotal + this.tax
    };
  });

.html:

 <div controller="BookingCtrl">
    <form name="bookingForm" ng-submit="">
        <div class="form-fields">
            <label for="checkin">Check In</label>
            <input id="checkin" name="checkin" placeholder="dd-mm-yyyy" type="text" ng-model="booking.checkin">
            <label for="checkout">Check Out</label>
            <input id="checkout" name="checkout" placeholder="dd-mm-yyyy" type="text" ng-model="booking.checkout">
            <label for="guests">Guests</label>
            <select ng-model="booking.guests" ng-options="value for value in values"></select>
            <ul>
                <li>{{booking.checkin}}</li>
                <li>{{booking.checkout}}</li>
                <li>{{booking.nights}}</li>
                <li>{{booking.guests}}</li>
                <li>{{booking.cost}} x {{booking.nights}}</li>
                <li>Tax</li>
                <li>Total</li>
            </ul>
            <ul>
                <li>{{booking.pretotal}}CND</li>
                <li>{{tax}}CND</li>
                <li>{{booking.total}}</li>
            </ul>
            <input type="submit" value="Submit" ng-disabled="bookingForm.$invalid">
        </div>
    </form>
</div>

另外,我最初想在控制器中使用this/self语法,而不是使用$scope。这效果很好,但我无法在视图中显示值。(绑定到输入的那些将显示,但这仅仅是由于数据绑定,它们不会显示初始值。如果有人可以解释为什么会这样,请告诉我。

即为什么控制器中的这没有在视图中显示值

var self = this;
self.booking = {
      checkin: null,
      checkout: null,
      guests:  null,
      nights: null, 
      cost: null,
      pretotal: this.nights * this.cost,
      tax: 0,
      total: this.pretotal + this.tax
    };

但这确实做到了:

$scope.booking = {
  checkin: null,
  checkout: null,
  guests: null,
  nights: null, 
  cost: null,
  pretotal: this.nights * this.cost,
  tax: 0,
  total: this.pretotal + this.tax
};

范围对象 ($scope) 使控制器和视图能够相互通信。 如果将属性放在 self 而不是 scope 对象上,则视图无法使用它们,因为它们是控制器本身的属性,而不是 scope 对象。 在视图中对输入元素进行数据绑定时,Angular 会在它创建并传递给控制器的范围对象中查找绑定属性。如果找不到它们,它将在 scope 对象中创建属性并将输入绑定到它们。另一方面,如果你有一个在控制器中给定值的范围对象的属性,那么 Angular 会将该属性绑定到你将数据绑定到该属性的输入。 因此,输入将在页面上具有一个初始值,该值是控制器设置的任何值。

您可以使用 this/self 语法 - 但您应该使用 ControllerAs 语法。

<div ng-controller="BookingCtrl as book">
  <p>{{ book.booking.checkin }}</p>
</div>

阅读文档中的所有回合:)

https://docs.angularjs.org/api/ng/directive/ngController