2

Within an ng-repeat block I have textboxes. To detect when the content differs from the original, the original data is stored in a variable.

<tr data-ng-repeat="p in products">
  <td>
    <textarea data-elastic data-ng-model="p.comment" data-ng-change="hasChanged=checkChange(original, rnd.comment);" data-ng-init="original=rnd.comment; hasChanged=false"></textarea>
  </td>
  <td class="save" ng-show="hasChanged" ng-click="save(p, original)">Save</td>

A save button is shown only when the content has changed. After a successful save the original value should be updated to the new value.

I can do it like this with a function in the controller:

$scope.save = function (p, original) {
  //...successful save
  this.original = p.comment; //this works
  original = p.comment; //this does not
}

Relying on some implicit scope in the form of 'this' doesn't seem sensible.

Why doesn't updating the variable (original = ...) work? What's a smarter way to do this?


Based on comments I've updated it as follows:

ng-click="save(p, this)"

$scope.save = function (p, scope) {
 //...successful save
 scope.original = p.comment; //this works
}

This seems failrly sensible now. Is passing scope around like this considered bad practice or acceptable?


Products is defined as follows:

productStatusApp.controller('productStatusCtrl', function ($scope, $http, cid) {
   $http.get('api/company/products/' + cid).success(function (data) {
      $scope.products = data.products;
   });
Vok
  • 457
  • 5
  • 19
  • Perhaps... `$scope.original`...?! – deceze Oct 01 '15 at 08:36
  • If you want "original" changes to be visible from outside the function, you need to wrap it inside an object. Ex. var obj = { original: 123 }. Then inside the function obj.original = 456. Then changes to obj will be visible from outside. – MichaelAttard Oct 01 '15 at 08:37
  • http://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language – MichaelAttard Oct 01 '15 at 08:38
  • See [JavaScript Prototypal Inheritance](http://stackoverflow.com/a/14049482) – Captain Oct 01 '15 at 08:52
  • What is rnd.comment is this case? Where is it defined? Your current ng-model points at p.comment, so if the code that is not seen is straight forward it would save directly inte the original product (unless the products list is a copy). Posting the entire controller, or at least anything that has to do with these products and comments, would probably help. – Erik Honn Oct 01 '15 at 09:39
  • Apologies - I had tried to shorten names to be more concise on SO. Edited to replace rnd with p. p.comment is a string. – Vok Oct 01 '15 at 09:57

1 Answers1

0

I've found the best way to avoid this kind of problems, is to use services

https://docs.angularjs.org/guide/services

http://viralpatel.net/blogs/angularjs-service-factory-tutorial/

some rough code(use it just for pointers, not tested at all)

<tr data-ng-repeat="p in ProductsService.products">
   <td>
       <textarea data-elastic data-ng-model="p.comment"></textarea>
   </td>
   <td class="save" ng-show="p.originalComment!==p.comment" ng-click="ProductsService.save(p)">Save</td>
</tr>

and

var module = angular.module('app', []);
module.service('ProductsService', function () {
   var products = [postA,postB,...,PostC];

   products = products.map(function(p){p.originalComment=p.comment});

   var save = function(p){
         p.originalComment=p.comment;
         someAjaxRequest(function _callback(err,response){....})
   }

   return {products:products,save:save};
});

and

module.controller('ProductsController', function ($scope, ProductsService) { 
    $scope.ProductsService= ProductsService;
});

They also allow better readability , WIN WIN

catalint
  • 1,895
  • 17
  • 17