2016-02-04 3 views
1

У меня есть требование динамического отображения итоговой суммы на основе выражения, возвращаемого службой. См. Структуру элемента выборки ниже. Значение свойства привязывается к текстовому вводу. Если какое-либо из входных значений изменяется, суб-итог обновляется в соответствии с выражением в метке. Каков наилучший способ сделать это?угловая вычисленная переменная из выражения

Примечание: номер пары имя/значение может варьироваться.

$scope.item = [ 
 
    {fieldName: "fname1", value: 2}, 
 
    {fieldName: "fname2", value: 5}, 
 
    {fieldName: "fname3", value: 4}, 
 
    {fieldName: "fname4", value: 6}, 
 
    {fieldName: "fname5", value: 3}, 
 
    {fieldName: "subTotal1", expression: "['fname1'] + ['fname2'] +['fname3'] +['fname4'] +['fname5'] +"} 
 
]

+0

Можете ли вы изменить свой сервис. ? –

+0

Я могу, если понадобится. Что ты предлагаешь? – Chen

ответ

0

О, Боже мой! Я сделал это! Посмотрите :)

Конечно, это решение не идеально. И это зависит от имени переменной, используемого в контроллере. Но это работает!

Живой пример на jsfiddle.

<form name="ExampleForm" id="ExampleForm"> 
    <div ng-repeat="item in items"> 
    <div ng-if="item.fieldName!='subTotal1'"> 
     <input ng-model="item.value"> 
     <my-ng-model n-name="{{item.fieldName}}" n-value="item.value" obj="obj"></my-ng-model> 
    </div> 
    <div ng-if="item.fieldName=='subTotal1'"> 
     {{item.expression }}={{$eval(item.expression)}} 
    </div> 
    </div> 
    {{obj|json}} 
</form> 

И JS контроллер:

.controller('ExampleController', function($scope, $parse) { 
$scope.obj = {}; 
$scope.items = [{ 
    fieldName: "fname1", 
    value: 2 
}, { 
    fieldName: "fname2", 
    value: 5 
}, { 
    fieldName: "fname3", 
    value: 4 
}, { 
    fieldName: "fname4", 
    value: 6 
}, { 
    fieldName: "fname5", 
    value: 3 
}, { 
    fieldName: "subTotal1", 
    expression: "obj.fname1 + obj.fname2 +obj.fname3 +obj.fname4 +obj.fname5" 
}];}) 

И директива ЯШ:

.directive('myNgModel', function() { 
var root = { 
    restrict: "E", 
    replace: true, 
    scope: { 
    nName: "@", 
    nValue: "=", 
    obj: "=" 
    }, 
    template: '<div></div>', 
    link: function(scope) { 
    scope.obj[scope.nName] = scope.nValue*1; 
    scope.$watch('nValue', function(value) { 
     scope.obj[scope.nName] = value*1; 
    }); 
    } 
} 
return root; }) 

ОБНОВЛЕНО

Сейчас он работает без ссылки на локальную переменную!

Живой пример на jsfiddle.

<form name="ExampleForm" id="ExampleForm"> 
    <div ng-repeat="item in items"> 
    <div ng-if="item.fieldName!='subTotal1'"> 
     <input ng-model="item.value"> 
     <my-ng-model n-name="{{item.fieldName}}" n-value="item.value" obj="obj"></my-ng-model> 
    </div> 
    </div> 
    <div ng-repeat="eval in evals"> 
    {{eval.expression }}={{$eval(eval.expression,obj)}} 
    </div> 
</form> 

Контроллер

.controller('ExampleController', function($scope, $parse) { 
$scope.obj = {}; 
$scope.items = [{ 
    fieldName: "fname1", 
    value: 2 
}, { 
    fieldName: "fname2", 
    value: 5 
}, { 
    fieldName: "fname3", 
    value: 4 
}, { 
    fieldName: "fname4", 
    value: 6 
}, { 
    fieldName: "fname5", 
    value: 3 
}, { 
    fieldName: "subTotal1", 
    expression: "fname1 + fname2 +fname3 +fname4 +fname5" 
}]; 
$scope.evals = []; 
angular.forEach($scope.items, function(item) { 
    if (item.expression) { 
    $scope.evals.push({ 
     expression: item.expression 
    }); 
    } 
});}) 

И директива

.directive('myNgModel', function() { 
var root = { 
    restrict: "E", 
    replace: true, 
    scope: { 
    nName: "@", 
    nValue: "=", 
    obj: "=" 
    }, 
    link: function(scope) { 
    scope.obj[scope.nName] = scope.nValue * 1; 
    scope.$watch('nValue', function(value) { 
     scope.obj[scope.nName] = value * 1; 
    }); 
    } 
} 
return root;}) 
+0

Привет, Степан, ваше второе решение - блестящее, которого я не понял. Это круто. – Chen

0

Если вам нужно вычислить значение, основанное на expresion собственности, вы должны сначала tokanize индикаторы поля вместе с их математическими операторами в выражении. Сложность этого процесса варьируется по типам математических показов, которые вы допускаете в выражении.

Например:

[fName1] + [fName2] - [fName3] // is a simple expression 
[fName1] * ([fName2] + [fName3]) // is complex than that 

Затем следует вычислить агрегированные значения из этих маркеров, сравнивая их с массивом.

-

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

Вы можете получить представление об этом методе в ответе this.

0

Я написал скрипку, чтобы решить вашу проблему. Это может быть улучшено, но на данный момент у меня нет времени. Вы можете сделать это сами.

Он основан на модели публикуемую:

$scope.item = [ 
    {fieldName: "fname1", value: 2}, 
    {fieldName: "fname2", value: 5}, 
    {fieldName: "fname3", value: 4}, 
    {fieldName: "fname4", value: 6}, 
    {fieldName: "fname5", value: 3}, 
    {fieldName: "subTotal1", expression: "['fname1'] + ['fname2'] +['fname3'] +['fname4'] +['fname5'] +"} 
    ] 

Для привязки к работе вы можете положить все, что в функцию, которая повторно оценивается при изменении свойства.

Проверить вне его HERE