Подтвердить что ты не робот

Новое в Angular - Вычисляемые переменные

Я перехожу к Angular из нокаута, и у меня есть несколько вопросов. Я предполагаю, что я должен делать что-то типа не angular.

http://jsfiddle.net/LostInDaJungle/BxELP/

I linked to jsfiddle so I didn't have to include my code here
Qaru will not let me post my question without a code block.

Вот очень простая скрипка, в которой излагаются две основные проблемы...

Задача 1: val1 и val2 инициализируются как 3 и 4, и добавить до 7 правильно. Однако, если вы изменяете одно из значений в текстовых полях, новое значение рассматривается как строка, и я получаю конкатенацию вместо добавления. Измените val1 на 4, и вы получите 44, когда это должно быть 8. Каков наилучший способ для этого поведения?

Задача 2: Вычисленные поля. Я могу получить вычисленное поле, используя фигурные скобки, такие как {{val1 + val2}}, и автоматическое обновление вычисленных полей при изменении базовой модели, но это совершенно неприемлемо. В моем полнофункциональном приложении мы генерируем "стоимость", которая используется несколько раз повсюду, и каждый раз при необходимости вычислять затраты, это боль. Не говоря уже о том, что когда этот расчет меняется, у меня теперь есть незавидная задача найти 15 разных мест, которые используют калькуляцию затрат и обновляют их все.

Кроме того, если я попытаюсь поместить ng-model = "cost" на вкладке с фигурными скобками, то фигурные скобки не работают. Таким образом, ничто не выскакивает на меня как способ привязать стоимость.

http://jsfiddle.net/LostInDaJungle/QNVwe/

Этот пример больше похож на структуру, которую я желаю. Однако, в отличие от ko.observable, вычисленные поля не обновляются, когда изменяются значения, генерирующие их. Решение шаблона, на которое все навязывали мне, - написать кучу обработчиков ng-change... Но это ужасно. Если изменения ширины меняют стоимость и меняют расчеты окупаемости и т.д. Это быстро становится запутанным беспорядком.

Оба этих метода не позволяют отделить логику от представления. Первый метод имеет мою бизнес-логику, встроенную в мой HTML. Метод два ставит целую кучу обработчиков ng-change в моем коде, который не сильно отличается от того, чтобы писать весь беспорядок обработчиков onChange в plain ol 'HTML. Если мне нужно сделать кучу обработчиков изменений ng, я бы так же быстро обработал onChange в Javascript, потому что я могу хотя бы объявить их за пределами моего уровня представления.

Здесь версия для нокаута:

http://jsfiddle.net/LostInDaJungle/eka4S/2/

Это больше похоже на то, что я ожидал бы... Ничто, кроме привязки данных к моим входам, все программные логики прекрасно содержатся в модели представления. Кроме того, поскольку моя вычислимая функция Javascript, мне не нужно почесать голову о том, как обеспечить, чтобы мои два значения были числовыми.

Так....

Вычисленные переменные: есть ли способ посмотреть основные переменные и автоматически обновить вычисленную сумму? Без необходимости похоронить мою программную логику в моем HTML?

Есть ли хороший способ, чтобы мои числа не превращались в строки?

Благодарим вас за помощь.

FYI, также отправленный в группы Google: https://groups.google.com/forum/#!topic/angular/0dfnDTaj8tw

4b9b3361

Ответ 1

Для вычисленного поля добавьте метод к вашему контроллеру.,.

$scope.cost = function() { return $scope.val1 + $scope.val2 };

а затем привязать его напрямую. Он будет знать, когда он должен пересчитываться по мере изменения его составляющих значений.

<div>{{cost()}}</div>

Ответ 2

Хорошо,

Несколько часов спустя, и я думаю, что у меня есть мой ответ.

Использование $scope. $watch.

$scope.$watch('(height * width) * 40', function(v) {$scope.cost = v;});

или

$scope.$watch('height + width', function() {$scope.cost = (Number(height) * Number(width)) * 40;});

Это автоматическое обновление любых вычислений для наблюдаемых переменных. И это дает мне способ работать с ними без необходимости жить внутри фигурных скобок.

Кроме того, вычисленные значения можно повторно использовать и отслеживать для каскадных обновлений:

$scope.$watch('height * width', function(v) {$scope.dim = v;});
$scope.$watch('dim * 40', function(v) {$scope.cost = v;});

Поэтому, если высота и/или ширина изменяются, dim обновляется, а так как dim изменен, стоимость обновляется.

Ответ 3

Я изменил свой третий вход на:

<input type="text" value="{{val1 * 1 + val2}}" />

который вызывает Angular.js для обработки значений как чисел, а не строк.

Вот fiddle. Я почерпнул ответ из здесь.

Ответ 4

О проблеме 1:

Если возможно, следует использовать тип ввода = "номер". Это правильно позаботится о разборе чисел. Даже если у вас более старый браузер angular, он позаботится о форматировании их как чисел.

О проблеме 2:

Ваш ответ хороший Джейсон, если вам просто нужно показать простой текст на экране. Однако, если вы хотите привязать вход с моделью к произвольному выражению, вам нужно что-то еще.

Я написал директиву, которую вы можете использовать для привязки ng-модели к любому выражению, которое вы хотите. Всякий раз, когда выражение изменяется, модель устанавливается в новое значение.

module.directive('boundModel', function() {
  return {
    require: 'ngModel',
    link: function(scope, elem, attrs, ngModel) {
      scope.$watch(attrs.boundModel, function(newValue, oldValue) {
        if(newValue != oldValue) {
          ngModel.$setViewValue(newValue);
          ngModel.$render();
        }
      });
    }
  };
})

Вы можете использовать его в своих шаблонах, например:

<input type="text" ng-model="total" bound-model="value1 + value2">

Или вот так:

<input type="text" ng-model="total" bound-model="cost()">

Где cost() - простая функция области, подобной этой:

$scope.cost = function() { return $scope.val1 + $scope.val2 };

Хорошо, что вы продолжаете использовать модель для ввода, и вам не нужно динамически обновлять свой атрибут value, что не работает в angular.

Ответ 5

Я новичок в AngularJS, но думаю, что можно использовать $parse:

http://docs.angularjs.org/api/ng/service/ $parse

Это интересно, если у вас есть выражение в виде строки. Вы можете использовать путь к свойствам и эту строку можно генерировать динамически. Это работает, если вы не знаете выражение во время компиляции, как eval(), но, вероятно, намного быстрее и, возможно, более безопасным (?).

Вот пример:

function Ctrl($scope,$parse) {
  var expression = 'model.val1 + model.val2';//could be dynamically created
  $scope.model = {
    val1: 0,
    val2: 0,
    total: function() { 
        return ($parse(expression))($scope); 
    }
  };
}

Ответ 6

u может связываться с функцией       

function CTRL ($scope) {
$scope.val1 = 3;
$scope.val2 = 4;
$scope.sum = function(){
   return ($scope.val1 *1 + $scope.val2 *1);
};

}

он будет работать одинаково выражение привязки будет работать, но в гораздо более сложных случаях нам нужны функции

Ответ 7

Функция $watch, которая доступна через переменную $scope, лучше всего подходит для этой работы, на мой взгляд.

$scope.$watch(function(scope) { return scope.data.myVar },
              function(newValue, oldValue) {
                  document.getElementById("myElement").innerHTML =
                      "" + newValue + "";
              }
             );

Функция $watch принимает: функция значения & Амп; функция слушателя

Приведенный выше пример взят из этой удивительной статьи: http://tutorials.jenkov.com/angularjs/watch-digest-apply.html

Прочитав это, я многому научился и смог реализовать решение, которое я искал.