How to make this directive return in ng-bind the sum of the results?

Asked

Viewed 773 times

2

angular.module( 'isfModFinance', [])
.directive( 'isfModFinance', function() {
      var validElementScope = angular.element('<div>{{ model.input }}</div>');
      var validElementTotal = angular.element('<div>{{ model.total }}</div>');
      var link = function ( scope, element, attrs) {
         scope.$watch("model.input", function (value) {
           validElementScope.addClass("finance-inputs");
          });

          scope.$watch("model.total", function (value) {
           validElementTotal.addClass("total-values");
          });


           scope.listModels = [];
           scope.maxlengh = '2';
                  scope.max = '10';
                  scope.min = '0';     
                  scope.size = '1';   
                  scope.labels = ['Valor'];
                  scope.classElements = 'default';  
                  scope.formatNumber = '2,.';
                  scope.unit = 'R$ ';
                  scope.total_view = 'R$ 0,00';



                  if (angular.isDefined(scope.setPlaceholder)) {
                     scope.placeholder = scope.setPlaceholder;
                  } 
                  if (angular.isDefined(scope.setMaxlengh)) {
                     scope.maxlengh = scope.setMaxlengh;
                  } 
                  if (angular.isDefined(scope.setMax)) {
                     scope.max = scope.setMax;
                  } 
                 if (angular.isDefined(scope.setMin)) {
                     scope.min = scope.setMin;
                  } 
                 if (angular.isDefined(scope.setSize)) {
                     scope.size = scope.setSize;
                  } 
                 if (angular.isDefined(scope.setStep)) {
                     scope.step = scope.setStep;
                  } 
                 if (angular.isDefined(scope.setClassElements)) {
                     scope.classElements = scope.setClassElements;
                  } 

                 if (angular.isDefined(scope.setNameLabels)) {
                     scope.labels = scope.setNameLabels.split(',');
                  } 
                 if (angular.isDefined(scope.setNumberFormat)) {
                     scope.formatNumber = scope.setNumberFormat;
                 } 
                 if (angular.isDefined(scope.setUnitLegend)) {
                     scope.unit = scope.setUnitLegend;
                 } 


                scope.elementView = '<div>';
                scope.labels.forEach(function(value, key) {
                scope.elementView += '<div class="' + scope.classElements + '">' +
                                    '<label>' + value + ' </label>' +
                                    '<input class="qtde" type="number" ng-model="model.qtde_' + key + '" ' +
                                    'placeholder="' + scope.placeholder + '" ' +
                                    'size="' + scope.size + '" ' +
                                    'maxlength="' + scope.maxlengh+'" ' +
                                    'max="' + scope.max + '" ' +
                                    'min="' + scope.min + '" ' +
                                    'step="' + scope.step + '">' +
                                    '</div>';
                 scope.listModels[key] = 'model.qtde_' + key;
                });

            var strnWatch =  "[" + scope.listModels.join(",") + "]";
        // console.log(strnWatch);
                 scope.$watch(strnWatch, function (data) {
                    var valor = 0;
                     var elementInputs = validElementScope.children(1).children(1).children(1).next();
                 angular.forEach(elementInputs, function(newVal, oldVal) {
                            console.log(newVal,'|',oldVal);
                            if (data == undefined || data == '' || isNaN(data)) {
                                valor += parseFloat(0);
                            } else {
                                valor += parseFloat(data);
                            } 
                         });
                      validElementTotal.text('Total: '+currencyFormatted(valor, scope.unit));
                   }, true);


              function currencyFormatted(value, str_cifrao) {
                    Number.prototype.formatMoney = function(c, d, t) {
                    var n = this, 
                        c = isNaN(c = Math.abs(c)) ? 2 : c, 
                        d = d == undefined ? "." : d, 
                        t = t == undefined ? "," : t, 
                        s = n < 0 ? "-" : "", 
                        i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "", 
                        j = (j = i.length) > 3 ? j % 3 : 0;
                       return s + (j ? i.substr(0, j) + t : "") +
                              i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) +
                              (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
                     };
                   scope.formatNumber.split("");
                 return str_cifrao + ' '+value.formatMoney(scope.formatNumber[0], scope.formatNumber[1], scope.formatNumber[2]);
               };
               validElementScope.html(scope.elementView);

  };

  return {
    restrict: 'EAC',
    scope: {
                setPlaceholder: "@",
                setMaxlengh: "@",
                setMax: "@",
                setMin: "@",
                setSize:"@",
                setStep:"@",
                setClassElements:"@",
                setNameLabels:"@",
                setNumberFormat:"@",
                setUnitLegend:"@",
            },  
    replace: true,
    template: "<div></div>",
    compile: function (tElem) {
    tElem.append(validElementScope);
    tElem.append(validElementTotal);    
        return link;
    }
  }
});

Here’s the directive I’m trying to make: http://jsfiddle.net/ivanferrer/0u8t9a4n/2/

She uses the angular element.: https://docs.angularjs.org/api/ng/function/angular.element

I need it to work exactly like in this example, in pure javascript: http://jsfiddle.net/k5hdxs2c/

  • Is there an impediment to using ng-change in html ? Because you could make a sum for each element. For example put in input data-ng-change perform a function and that function updates the ng-model of the total..

  • Can you show me an example based on the code shown?

  • ng-change="somarValor(model.qtde_' + key + ')" create this function within the directive: $scope.somarValor(value){&#xA; $scope.valorTotal += value;&#xA; } I thought this way because I imagined it would always show the total field, so you could put an ng-model on it, then you would always update it, and it would even serve for cases where the value was negative.

  • Do you really need it to be a directive? I found the logic a little complex. I made a solution right here in the controller, but if you want you can convert it to directive. Take a look https://jsbin.com/hadubi

  • @Daniel, the example you gave me served, see how it looked, if you want to publish your reply, I will mark as chosen: http://jsfiddle.net/ivanferrer/3ns0bxvq/

1 answer

1


Below is an example of a solution in controller unused directive.

Html

<div ng-app="myApp">
    <div ng-controller="myController">
        <div ng-repeat="item in itens">
            <label>{{item.label}}</label>
            <input type="number" ng-model="item.value" ng-change="sum()">
        </div>
        <hr>
        <label>Total: </label>
        <input ng-value="total | currency:'R$ ' " type='text' disabled="disabled">
        <hr>
    </div>
</div>

Coffeescript

myApp = angular.module 'myApp', []

myController = ($scope) ->
  $scope.itens = [
    {key: 'property_01', value: 0}
  ,
    {key: 'property_02', value: 0}
  ,
    {key: 'property_03', value: 0}
  ,
    {key: 'property_04', value: 0}
  ]

  $scope.sum = ->
    s = 0
    _.map $scope.itens, (i) -> s += parseFloat("#{if i.value then i.value else 0}".replace(',', '.'))
    $scope.total = s

myApp.controller('myController', ['$scope', myController])

Browser other questions tagged

You are not signed in. Login or sign up in order to post.