Mastering Polymorphism and Dependency Injection in AngularJS: Tips and Tricks for Success

This question revolves around design patterns. Rather than seeking a solution for achieving polymorphism in a service, I am interested in exploring the most widely accepted approach.

Imagine there is a service named getData which retrieves data from various sources such as a database, text file, or hardcoded input. The output is determined by the settings on the $scope within the controller. In this scenario, let's assume that the behavior of getData is influenced by the dataSource variable.

angular.module('testApp').controller('testController'), [$scope, myAwesomeService, function ($scope, myAwesomeService){
    $scope.dataSource = 'database'; //defines the source of the data

    $scope.getData = function() {
        //use myAwesomeService, get the data and output

        if($scope.dataSource ==='database') {
             return //perform operation based on 'database'
        }            

        else if($scope.dataSource ==='text') {
             return //perform operation based on 'text'
        } 

        else if($scope.dataSource ==='csvfile') {
             return //perform operation based on 'csvfile'
        } 
        else if($scope.dataSource ==='form') {
             return //perform operation based on 'form'
        } 

    }

}]);

Questions:

  1. How can polymorphism be generally achieved in Javascript? In JavaScript, achieving polymorphism may not have established best practices. Personally, I typically rely on interfaces by implementing dependency injection and passing objects that conform to the same interface. By calling a shared method from the controller, I maintain flexibility without getting involved in specific implementation details.

  2. How should this be implemented using AngularJS? Is there a standard Angular way of implementing polymorphism? Can you provide a conventional approach to achieving polymorphism in AngularJS?

Answer №1

Initially, I intended to leave a comment, but upon realizing its potential length, I decided to provide an answer instead.

In the realm of ES5, polymorphism and inheritance can be achieved through prototyping methods.

Here is a simple example:

function Auto(name,year){
   this.year=year;
   this.name=name;
}
Auto.prototype.showYear = function(){
   console.log(this.year);
}

function Car(name,year, model){
   Auto.call(this,name,year);
   this.model=model;
}
Car.prototype = Object.create(Auto.prototype);

//example usage
var car = new Car('BMW',2015,'320d');
car.showYear(); // outputs 2015

In the context of ES6, achieving the same can be done using `class` functions. For further details, refer to this insightful guide: HERE (it promises to be enlightening!)

Following is some code that might address your query. Hopefully, it aligns with what you are seeking:

function BaseService(){
    this.dataSource='database';
}
BaseService.prototype.getData = function(){
    console.log('base: get data');
}

function TextService(){
    this.dataSource='text';
}
TextService.prototype  = new BaseService();
TextService.prototype.getData = function(){
    console.log('child text: get data');
}

function CsvService(){
    this.dataSource='csv';
}
CsvService.prototype  = new BaseService();
CsvService.prototype.getData = function(){
    console.log('child csv: get data');
}

function FormService(){
    this.dataSource='form';
}
FormService.prototype  = new BaseService();
FormService.prototype.getData = function(){
    console.log('child form: get data');
}

angular.module('myApp').factory('awesomeService', function(){

    var service={};

    service.getData = function(dataSource){

        var sourceService;

        if(dataSource==='database'){
             sourceService= new BaseService();
        }

        if(dataSource==='text'){
            sourceService=new TextService();
        }

        if(dataSource==='csv'){
           sourceService = new CsvService();
        }

        if(dataSource==='form'){
          sourceService= new FormService();
        }

        return sourceService.getData(); // assuming getData returns a promise
   }

   return service;
});

angular.module('myApp').controller('myController', function($scope,awesomeService){
  var myDataSource='database';

  $scope.getData = function(){
    awesomeService.getData(myDataSource).then(function(data){
         $scope.result=data;
    });
  }
});

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

Ways to access text content in an HtmlTableCellElement

I am currently working on a jQuery tic-tac-toe project and facing an issue with iterating through the board to save the values of each cell in an array. I have tried using .text() and .value(), but both returned undefined index.html: <html> < ...

The specified property 'slug' is not found within the designated type 'ParsedUrlQuery | undefined'

I am faced with an issue in my code where I am attempting to retrieve the path of my page within the getServerSideProps function. However, I have encountered a problem as the type of params is currently an object. How can I convert this object into a stri ...

Display a partial form in Rails using Ajax

There is a form displayed in the image below: Next, I aim to render this partial from an ajax call, specifically from .js.erb. However, I am unsure how to pass an object to f from the partial. Take a look at the image below for reference: Is there a way ...

What is the best way to send user input text to a Vue method using v-on:change?

I am trying to pass the input value from my HTML to a Vue method called checkExist(). I need to get this value within the checkExist() method. Can anyone provide advice on how I can achieve this? I am new to Vue and could use some guidance. HTML: <inp ...

angular watch was not triggered

There is a single Angular app with a parent controller and a child controller. Within the child controller, there is a $watch function called WATCH-CHILD that monitors OBJ-CHILD and triggers an $emit event. The parent controller includes a listener for the ...

The Vuex commit has exceeded the maximum calstack size limit

Currently facing an issue https://i.sstatic.net/l1WWH.png The error seems to be isolated to this specific section mounted() { this.$nextTick(() => { let ctx = this.$refs.canvas.getContext('2d') let { chartType, dataOptions ...

send JSON data to a Spring MVC endpoint

Here is the controller signature I have tried using @RequestBody: @RequestMapping(value = "/Lame", method = RequestMethod.POST) public @ResponseBody boolean getLame(@RequestParam String strToMatchA, @RequestParam String strToMatchB) {} This is the json I ...

What could be the reason behind Lottie rendering an SVG element outside of its parent div?

After struggling with this issue for an entire day, I'm seeking help to implement an animation using Lottie on my website. The animation format is 1080*1920, but the problem arises when trying to fit it within a div. The dimensions of the div are set ...

Having trouble uploading images on Wordpress?

There have been persistent errors in the admin area for several days now: An unexpected SyntaxError: expected expression, but received '<'. These errors are appearing in files moxie.min.js, plupload.min.js, wp-plupload.min.js As a result, w ...

Angular view password reset in Laravel 5.1: Understanding CSRF token validation

I have successfully customized the default Laravel authentication to function as an API for my AngularJS project. So far, everything is running smoothly. Users can go to /reset, enter their email address, receive an email with a password reset link that di ...

The functionality of the button is affected when it is placed on the same line as a h1 heading

My goal is to have the page title and profile button aligned on the same line in the header of each page. However, I've encountered an issue where the button doesn't function properly when placed on the same line but works fine when separated ont ...

$watch will not be activated unless a full refresh is completed

I am using a $watch function to keep an eye on an array called menuItems within the MenuFilter service. $scope.filterMenuItems = MenuFilter.menuItems; $scope.$watch(function () { return MenuFilter.menuItems; }, function (newVal, oldVa ...

Can you please provide me with information on how I can send messages to US numbers using a toll-free number?

I attempted to utilize this code in the SNS console, but it showed a failure. I am seeking guidance on how to send a message using a TFN number. async sendMessage(testId: number) { const mobileNo = test.customer.phoneNo; const params = { Message: ...

Problem encountered when implementing multiple filters in Vanilla JavaScript

I am facing an issue with my HTML page that contains multiple filters using Vanilla JavaScript (no jQuery). The filtering process involves counting matches of filter selections against the data attributes of each element. However, I'm puzzled as to w ...

Enforce the text inside the child div to perfectly fit within the parent container

I have a challenge with two div elements in my HTML code as shown below: <div id="parent"> <div id="child"> <p class="child-text"> ..... </p> <a class="child-link"> ..... </a> <p class="ch ...

The code to trigger the button with the ID 'Button' using Document.getElementById() is not executing the associated code-behind

Having just started coding in javascript/VB.NET, I am struggling to get my Button2 onClick event to work properly. The Code-Behind Click Event for Button1 in Page.aspx.vb: Protected Sub _lnbComments_Click(ByVal sender As Object, ByVal e As System.EventAr ...

Looking for assistance in correctly identifying types in react-leaflet for TypeScript?

Embarking on my 'first' project involving react-scripts-ts and react-leaflet. I am attempting to create a class that should be fairly straightforward: import {map, TileLayer, Popup, Marker } from 'react-leaflet'; class LeafletMap exte ...

Encountering difficulty retrieving information in an Angular application on an iPad mini device

I am currently developing an angular application for a dashboard. The issue I am facing is related to making http requests from my controllers. Everything works perfectly when I build and run the project using grunt on my machine, fetching data from the ex ...

What happens when the `.push` command runs the "Undefined" function in jQuery - is it possible to execute a number instead?

My script is quite simple - I'm trying to use the push method to add the result of a function called dNumber into the variable named pattern. However, every time I try this, the result is always "undefined". Oddly enough, when I try pushing just plain ...

Rerendering of a React component occurs upon a change in its state

Previously, my form was functioning flawlessly. However, after making a few modifications to the state variables, the input field now loses focus upon a state change. I am utilizing MUI and everything was working perfectly until this sudden issue arose f ...