Automatically rehydrate an instance using Angular and JavaScript

REVISION

Special thanks to Shaun Scovill for providing an elegant solution using lodash

    // Creating an instance and injecting server object - within the ChartService implementation below
    var chart = new Chart(serverChartObject);

   // Replacing the Chart factory with the following code to simplify the object constructor creation using the server object and initializing 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));
        };
    }

DEVELOPER TOOLS

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

QUERY:

I'm exploring better approaches to automating hydration and protection of an AngularJS / JavaScript object instance.

SCENARIO

In this scenario, I retrieve a collection of chart objects from Laravel 5.1 backend (or any other backend returning a JSON object). A service module called ChartService is used to parse this data into JavaScript Chart objects.

GOAL

I aim to achieve the following with minimal code:

  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

INITIAL APPROACH

I initially employed

Object.defineProperty(Chart, 'app_id', { value: 1 });
along with protected approaches mentioned above. However, if I execute chart.app_id = 3, it overwrites the app_id. On the other hand, Object.freeze(chart) prevents all properties from being altered or modified.

CURRENT STRATEGY

NOTE: Some code has been omitted for brevity, apologies if context was compromised.

define([
    'angular',
    'lodash'

], 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,
                    chart,
                    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
                        Object.freeze(chart);
                    })
                }
            }
        };

        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;
            self.data = 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);

});

Answer №1

To make your Chart constructor more concise, consider utilizing a combination of lodash functions such as assign and pick. Here's an example:

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How to Properly Implement app.use() in Express for Middleware

What is the reason behind some middleware functions being passed in with invocation parentheses, while an anonymous function is passed in without being invoked? app.use(logger()); app.use(bodyParser()); If logger() is evaluated immediately and the return ...

Why will the experimental activation of React concurrent features in Nextjs 12 disable API routes?

I just upgraded to Next.js version 12 and set up some API routes (e.g. "/api/products"). These routes were functioning properly, but when I enabled concurrentFeatures: true in my next.config.ts, the API routes stopped working. The console display ...

Ways to retrieve my PHP output and display it on a page using Ajax

I'm struggling to combine the functionalities of a PHP script and Ajax on my website. I want to update content without reloading the page but facing issues. Although I can send input data through Ajax, I'm unable to retrieve the results effectiv ...

React JS Calendar

I'm currently working on a project where I need to create a calendar component using React. The design requires the days to be displayed like in the Windows calendar, starting from Sunday even if it's another month and ending with Saturday. The ...

Using React: What is the best method for handling asynchronous requests to fetch a FirebaseToken and subsequently utilizing it in an API request?

My React app is interacting with an API through a Client component. Components can access the Client like this (example in the componentDidMount function of the Home page, where I retrieve a list of the user's items): componentDidMount() { let u ...

Issues with navigation menus in Bootstrap/Wordpress

My mobile drop-down menu is giving me some strange issues. When you toggle the button, the menu briefly appears just below the button before moving to its correct position. Sometimes it doesn't work at all, and clicking has no effect. You can witnes ...

Using jQuery to trigger a click event on a radio button prevents the button from being checked

Having trouble with using the .trigger("click"); function on radio buttons to activate a button in a form. When I use the code below, the button is triggered as expected. However, it seems to be interfering with the radio button, causing it to appear chec ...

Is there a way to assign retrieved data to the $scope.variable?

I'm relatively new to both JavaScript and Angular. I have a piece of code that fetches data from an API and successfully prints it to the console, but I'm facing issues when trying to assign this data to $scope.saveData. It seems to only work wit ...

Creating a Javascript function to turn lights off using CSS manipulation, similar to the feature found

Is there a way to use JavaScript to obscure all elements on a page except for one specific HTML element? This web application is optimized for Chrome, so CSS3 can also be utilized. ...

Error: The value of _This.props is not defined

Hey there, I am new to working with React Native and could really use some assistance with this issue: TypeError: _props.goToScreen is not a function. Any help would be greatly appreciated, thank you in advance! In my Profile.js file, I am trying to click ...

Facing compatibility issues with ng-view on Microsoft Edge

While testing my application on Microsoft Edge, I encountered an error: app.config( function ($routeProvider) { $routeProvider. when('/logout', { template: '<logout-page></logout-page>&a ...

utilizing an ajax request to clear the contents of the div

When I click on Link1 Button, I want to use ajax to empty the contents in the products_list div <button type="w3-button">Link1</button> I need help with creating an ajax call that will clear the products in the product_list when the link1 but ...

The issue arising where the callback function fails to execute after making an AJAX POST request

Within my function, I have an AJAX call that I want to make reusable. When the AJAX call is successful, I need to callback a function. var ajaxPostCall = function(data , url ,callback){ // Return the $.ajax promise $.ajax({ data: data, dataType: ...

Objective subject for an element within a :not operation

I have a function that specifically excludes a style on links by targeting their IDs. Each of my links has an ID, so I use that to exclude the style. a:not([id='hopscotch_logo'] { color: red; } Now, I also want to find links that are children o ...

Tips for modifying hover effects using jQuerystylesheet changes

I attempted running the following code snippet var buttonElement = $('<button>Button</button>'); $('body').append(buttonElement); buttonElement.hover().css('background-color', 'red'); Unfortunately, the ...

Tips for returning JSON data using AJAX

When working with native JS, I am familiar with using AJAX to display the output from PHP/mySql that is not Json Encoded in the element "some_id" like this: <script> function addItem(value) { xmlhttp = new XMLHttpRequest(); xmlhttp.onrea ...

The process to reset a component's state when using router.push to navigate back to the same component

I am facing an issue with resetting the state on router.push in my project. I have a header component that includes a search option. When a user searches for something, router.push redirects them to '/search/${search}'. On the search page (SSR), ...

Implementing Ajax functionality in MVC 3 to return a partial view

I wanted to express my gratitude for this invaluable site that has taught me so much. Currently, I am working on an MVC3 component where I need to populate a selectlist and upon user selection, load a partial view with the relevant data displayed. Everythi ...

What is the best way for OnSubmit to access an external file?

Recently, I adjusted this code snippet to include the onsubmit attribute with a validation function call. Instead of having the validate function within the same file, I moved it to an external file for better organization. Now, I am wondering how do I e ...

How to use JQuery UI sortable to automatically scroll to the bottom of the page

Having trouble with a few sortable tables and here is how I initialized the sortable object: var options = { helper: customHelper, handle: ".moveTargetDeliverables", containment: "#fieldset_deliverables_summary", tolerance: 'pointer&a ...