1

We have tried angular.copy and angular.extend. Both of these, though, copy property values. How do we copy one object's properties, without their values, to another object?

Here is a fiddle with our attempts based on how-to-quickly-clear-a-javascript-object.

angular.module('App', []);

function Ctrl($scope) {

    function copyNotValues(obj) {
        var newObj = angular.copy(obj);
        for (prop in newObj) {
            if(newObj.hasOwnProperty(prop))
            {
                newObj[prop] = null;
            }
        };
        return newObj;
    }

    $scope.master = {
        foo: 'original foo',
        bar: 'original bar'
    };

    $scope.copy = angular.copy($scope.master);
    $scope.extend = angular.extend($scope.master);
    $scope.copyNotValues = copyNotValues($scope.master);

}
Community
  • 1
  • 1
Shaun Luttin
  • 133,272
  • 81
  • 405
  • 467

2 Answers2

2

JavaScript doesn't have the concept of classes. It uses Prototype inheritance which means you can only create a new object by copying another object. When doing that you get the properties.

You can get around this by creating a "master" object without property values. Something like this:

master = {
  foo: '',
  bar: ''
};

Then you can create new 'instances' of the object with the new keyword:

$scope.master = new master();
$scope.master.foo = 'original foo';
$scope.master.bar = 'original bar';

When you need to create a new instance of the object, go back to the original, not your copy:

$scope.masterCopy = new master();

This is really a JavaScript issue and not an Angular specific issue. I suppose you could, theoretically, write a function to create a new instance of an object and then loop over the properties to set them all to null or empty strings.

JeffryHouser
  • 39,401
  • 4
  • 38
  • 59
  • 1
    Thanks for that! My approach will be to use angular.copy(), loop over the new object, and set each of it's properties to null. Creating a "master" object is might be good for another situation, because my object-of-interest comes from a REST call and has many properties, so creating a master will be to much code duplication. – Shaun Luttin Feb 13 '14 at 00:48
  • 1
    @ShaunLuttin In my ActionScript experience; it made a lot of sense to duplicate objects on the server side and in the client. But since JavaScript is a loosely typed language, you're probably right that the overhead doesn't make sense. I'm pretty sure that a for each loop will give you all the properties of an object; and you should be able to encapsulate that into a utility function for easy reuse. Good luck! – JeffryHouser Feb 13 '14 at 00:56
  • 1
    Great tips! We are already duplicating the objects on the server side and the client. On the server, we have both a binding model and a view model. And on the client, we have the ng-model that exists in the HTML template. If we were also to duplicate the model in the ng-controller, we would then have four representations of the same model! Three seems enough overhead, as you mention. The JavaScript for loop did the trick in a utility function that we put into an Angular service. Thank you for the encouragement! – Shaun Luttin Feb 13 '14 at 01:00
  • @JeffryHouser I understand using angular.copy() in this case. However, when I tried creating instance the way JeffryHouser mentions it, I am getting an error that says master is not a constructor. Anything I am missing on? – Swanidhi Jan 11 '15 at 09:38
  • @Swanidhi Without seeing a sample; I'm, not sure. Can you share a Plunker demonstrating the problem? – JeffryHouser Jan 12 '15 at 12:06
0

My solution is as follows you can use angular.copy and pass the object .Before that define the object with blank curly braces.The code is as follows.I have used some other example,but the underline approach is same.

angular.module('formExample', [])
  .controller('ExampleController', ['$scope', function($scope) {

    $scope.sa = {}; //declaring sa object
    $scope.ba = {}; //declaring ba object
    $scope.update = function() {
      $scope.ba = angular.copy($scope.sa);
    };

  }]);
<!doctype html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Example - example-example32-production</title>


  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0-beta.2/angular.min.js"></script>



</head>

<body ng-app="formExample">
  <div ng-controller="ExampleController">
    <form novalidate class="simple-form">
      <h3>Shipping Address</h3>
      Name:<input type="text" ng-model="sa.name" ng-change="sameAddress && update()" placeholder="in" /><br/> Age:
      <input type="text" ng-model="sa.age" ng-change="sameAddress && update()" placeholder="age" />
      <br /> Street:

      <br />

      <h3>Billing Address
        <input type="checkbox" ng-model="sameAddress" ng-change="sameAddress && update()" />Copy
      </h3>

      Name:<input type="text" ng-model="ba.name" ng-disabled="sameAddress" placeholder="out" /><br/> Age:
      <input type="text" ng-model="ba.age" ng-disabled="sameAddress" placeholder="age" />
      <br />

      <br />

    </form>

  </div>


</body>

</html>

The pluner is here