Angular / JavaScript Auto Hydrate An Instance

- 1 answer


thanks to Shaun Scovill's elegant answer below using lodash

    // create instance and inject server object - inside of the ChartService below
    var chart = new Chart(serverChartObject);

   // replace Chart factory with the following code to streamline the creation of the object constructor using the server object as well as hydrate it!

    Chart.$inject = [];
    function Chart() {

        return function(serverChartObject) {
            var keys = ['app_id', 'article_id', 'section_id', 'data', 'headline', 'legend', 'source', 'source_url', 'subtitle', 'summary', 'width', 'height'];
            _.assign(this, _.pick(serverChartObject, keys));


Angular : 1.4.7 RequireJS: 2.12 Laravel 5.1.x Lodash 3.10.1


I'm wondering if there is a better approach to auto hydrating and protecting a AngularJS / JavaScript object instance.


In the example below I GET a collection of chart objects from a Laravel 5.1, but could be any backend as it returns a json object. I have a service module, ChartService, that then parses out the data into a JavaScript Chart objects.


With the least amount of code I'm hoping to achieve the following:

  1. create a Chart object instance
  2. hydrate the JS object with server chart data
  3. protect the object data properties OR a subset such as article, app_id, section_id and data


I used Object.defineProperty(Chart, 'app_id', { value: 1 }); and on the above mentioned protected approaches but if I then execute chart.app_id = 3 it overwrites the app_id versus Object.freeze(chart) that stops all properties from being overwritten or modified.


NOTE: Removed a lot of the code for brevity sake so apologies if I removed too much for context to make sense.


], function(angular, _) {
    'use strict';

    ChartService.$inject = ['$http', '$q', '$sce', '$rootScope', 'api', 'Chart'];
    function ChartService($http, $q, $sce, $rootScope, api, Chart) {

        var chartService = {
            charts: [],
            // NOTE : call parse from external source
            parseCharts: function(items) {
                var self = this,
                    articleId = null,
                    sectionId = null;

                // NOTE : items are a collection of chart objects from Laravel
                if (angular.isDefined(items) && Object.keys(items).length > 0) {
                    // NOTE: c = chart server object
                    _.each(items, function(c,k) {
                        // factory Chart instance
                        chart = new Chart();
                        // NOTE : hydrate chart instance with c (server chart object data)
                        chart = hydrateInstance(c, chart);
                        // freeze object

        function hydrateInstance(obj, instance) {
            for (var prop in obj) {
                if (obj.hasOwnProperty(prop) && instance.hasOwnProperty(prop)) {
                    instance[prop] = obj[prop]
            return instance;

        return chartService;

    Chart.$inject = [];
    function Chart() {
         * Constructor, with class name
        function Chart(app_id, article_id, section_id, data, headline, legend, source, source_url, subtitle, summary, width, height) {

            var self = this;
            self.app_id = app_id;
            self.article_id = article_id;
            self.section_id = section_id;
   = data;
            self.headline = headline;
            self.legend = legend;
            self.source = source;
            self.source_url = source_url;
            self.subtitle = subtitle;
            self.summary = summary;
            self.width = width;
            self.height = height;
        // removed rest of object / prototype properties for brevity sake

        return Chart;

    return angular.module('cmo.content.charts', [

        // remove config for brevity
        .factory('Chart', Chart)
        .service('ChartService', ChartService);



You could shorten your Chart constructor using a couple of lodash functions (assign and pick), like this:

function Chart() {
    return function(config) {
        var keys = ['app_id', 'article_id', 'section_id', 'data', 'headline', 'legend', 'source', 'source_url', 'subtitle', 'summary', 'width', 'height'];
        _.assign(this, _.pick(config, keys));