Avoiding repetitiveness in AngularJS

I have 8 controllers using 12 common functions, but each controller has 3-4 unique functions. How can I avoid repeating myself in each controller while still utilizing a common service? Here is an example of my current code:

app.controller("ArticleController",['$scope','$http','dataService',function($scope,$http,dataService){

$scope.comments={};
$scope.articles = {articles:[]};
$scope.reachedEnd = false;
$scope.getArticles //implemented differently for each controller
//Here it is used to fetch latest articles
/* common 12 functions 
   to deal with dom events like new comments, upvotes, etc.
*/
function getArticlesSuccess(articles){
    articles.articles.forEach(function(article){
        $scope.articles.articles.push(article);
    });
    $scope.reachedEnd = articles.reachedEnd;
}

// Common functions handled by dataService
$scope.addToReadingList = function(id,userid){
    dataService.addToReadingList(id,userid);
};

$scope.removeFromReadingList = function(id,userid){
    dataService.removeFromReadingList(id,userid);
};

$scope.upvote = function(id,userid){
    upvoteIncrementer(id,userid);
    dataService.upvote(id);
};

$scope.deleteComment = function(commentId){
    dataService.deleteComment(commentId);
};

var upvoteIncrementer = function(id,userid){
    console.log(id);
    $scope.articles.articles.forEach(function(article){
        console.log(article);
        if(article && article._id === id && !article.votes.set){
            if(article.votes.down.indexOf(userid)>-1){
                article.votes.down.splice(article.votes.down.indexOf(userid));
                console.log('removed vote');
            }
            article.votes.up.push(userid);
            article.votes.set = true;
        }
    });
}

// Similar pattern for other operations

}]);

Code snippet for another controller:

app.controller("AnotherController",['$scope','$http','dataService',function($scope,$http,dataService){
$scope.comments={};
$scope.articles = {articles:[]};
$scope.reachedEnd = false;
$scope.getArticles //implemented differently for each of the controllers
//Here it is used to fetch top articles by the day
/* common 12 functions */
}]);

EDIT: Added dataservice.js

(function(){

angular.module('newstalk')
    .factory('dataService',['$http','$q',dataService]);

function dataService($http,$q){
    return {
        getArticles : getArticles,
        postComments : postComments,
        addToReadingList : addToReadingList,
        getReadingList : getReadingList,
        upvote : upvote,
        downvote : downvote,
        getComments : getComments,
        removeFromReadingList : removeFromReadingList,
        deleteComment : deleteComment
    };

    // Functions logic here
    
}
})()

Please suggest a way to reduce code duplication and make changes in only one place to affect all controllers.

Answer №1

Utilizing a function as a service allows you to create an object containing reusable functions for use across controllers. By calling this function in each controller and providing parameters, you can customize the functions based on the specific controller.

app.factory('myStuff', function($http) {
  return function(urlForController) {
    return {
      foo: function() {
        // utilize the parameters within your functions
        return $http.get(urlForController);
      },
      bar: //etc
    };
  };
});

app.controller('myCtrl', function($scope, myStuff) {
  // invoke the service function with controller-specific parameters
  $scope.myStuff = myStuff('/whatever');
});

You can also pass the controller's $scope into the service so that the functions can directly manipulate it if needed.

$scope.myStuff = mystuff($scope, '/whatever');

// the service:
return function(scope, urlForController) {

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

Tips for showcasing a personalized design using ng-repeat

Upon reflection, I realized that my original question needed improvement, so here is the revised version. Hello! I am new to Angular and I am attempting to create a custom layout for my data list using ng-repeat. I want to display different model values w ...

How can you effectively use a table filter extension to sort through dropdown values?

Is there a way to update the dropdown values based on new data after applying the first filter? For example, only displaying $0 in the second dropdown menu? Essentially, I want to filter the values in a table and then have the dropdown options reflect the ...

Automatically fill in a text box with previously saved information

Does anyone have suggestions on how to create this type of textbox or what it is called? (View original image here) ...

How can I transfer a particular data value from a div to JavaScript within Laravel 5.0?

Displaying separate square divs based on integers retrieved from the database. This is the front-end view. I want to pass the room ID (code) to a JavaScript function when clicking on these div elements. https://i.stack.imgur.com/aIYTr.png Below is my cur ...

Using express.js to transfer an uploaded image to Amazon S3

Currently, I am faced with an issue of passing an image uploaded from a react application through express to a managed s3 bucket. The s3 bucket is created and managed by the platform/host I am using, which also generates upload and access urls for me. So f ...

What crucial element is lacking in this AJAX call snippet?

My apologies for not including the full code for context, as I am still very new to this. Here is the snippet of code from the signup.php file: <?php session_start(); include('connection.php'); // Validation messages $mis ...

Using THREE.js: Finding the nearest point between two rays in a THREE.js environment

In my current project with THREE.js, I am working with two THREE.Ray objects. Both rays have an origin point represented by a Vector3 and a direction indicated by another Vector3. I am currently exploring how to determine the nearest intersection point be ...

Passing variables from the browser to Protractor can be achieved by utilizing the browser

I am currently in the process of testing a single page application that involves making a GET request to a specific API endpoint and expecting certain results. To facilitate this testing process, I have mocked the API using the $httpbackend object. My mai ...

Angular promise objects provide access to important values

let userRequest = $http({ method: 'POST', url: $rootScope.apisrvr + 'user/user_signin', data: { username: $scope.user.username, password: $scope.user.password }, ...

Is it possible to utilize href alongside the urlRouterProvider?

Within my angularjs application, I opted to switch from using ngRoute (routeProvider) to ui.router (urlRouterProvider) module and stateProvider for transitioning between different states in the app. However, I recently discovered that ui-router only suppo ...

Animating the Bookmark Star with CSS: A Step-by-Step Guide

I found this interesting piece of code: let animation = document.getElementById('fave'); animation.addEventListener('click', function() { $(animation).toggleClass('animate'); }); .fave { width: 70px; height: 50px; p ...

Have the input text and submit button aligned on the same line for a sleek

While attempting to create a search box and search submission button, I have tried various methods to align the button and text box on the same line without success. Below is the code snippet I am currently using. return ( <Form onSubmit={submitHa ...

Positioning Thumbnails with Jquery Cycle Plugin

Initially, my inquiry is quite similar to a question that was previously posted here. However, the difference lies in the fact that I am utilizing WordPress and the nextgen gallery plugin to handle my images. mygallery/image1.jpg mygallery/image2.jpg and ...

Guide to generating an array entry for every line of a text file in node.js

Struggling with converting each line of a text file into an array entry in node.js The array I am working with is named "temp." The code below successfully prints out each line: var temp = []; const readline = require('readline'); const fs = re ...

Ways to update list item text with jQuery

I am attempting to create a button that can replace the content of a list item. Although I have looked at other solutions, I keep encountering this error message: Uncaught TypeError: Object li#element2 has no method 'replaceWith' I have experime ...

Transferring an Applescript list to ExtendScript in Javascript as an array for use in InDesign

Situation Background I have a large number of Applescripts (AS) that designers rely on in InDesign to streamline production workflows. These AS scripts handle a lot of OS interactions that JavaScript cannot replicate, so transitioning away from AS is not ...

Maintaining the position of the input cursor when using the arrow up and down keys in AngularJS directive

I am currently developing a custom "typeahead/autocomplete" directive. element.bind("keydown keypress", function (event) { if(event.which === 38 || event.which === 40) { var increment = event.which === 38 ? 1: -1; ... .. ...

Adjusting the height in AngularJS based on the number of items in a table

I've developed a straightforward AngularJS application with multiple tables on one page. In order to add scrolling functionality, I initially used a basic CSS code snippet like: tbody { overflow: auto; } I also experimented with the https://github. ...

Having trouble toggling the dropdown submenu feature in a Vuejs application?

.dropdown-submenu { position: relative; } .dropdown-submenu .dropdown-menu { top: 0; left: 100%; margin-top: -1px; } <div class="dropdown"> <button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown">Tutorial ...

Is it true that URL parameters can be found in two distinct locations within this.props in react-router?

<Route path="lookbook" component={Photos} onEnter={onPageEnter}> <Route path=":photoIdentifier" component={PhotoDetailsModal} onEnter={onPageEnter}> </Route> </Route> While in the PhotoDetailsModal, I used console.log to check ...