Design of Angular project structure

Building an app in Angular involves consuming various APIs and providing options for users to select, which are then recorded and sent back to the server.

The design of the app is structured as follows:

  • All common logic is placed in the Main Controller, with other options separated into different controllers that act as children of the main controller.
  • The Main Controller retrieves all necessary data required to run the app, which is then accessed by all child controllers.
  • To ensure that the data is loaded before execution, promises are attached to the scope so that child controllers are aware when the data is available.
  • Data updating functionalities within child controllers have been moved to the main controller to consolidate updates that occur on a single object.
  • Communication between child and main controllers is facilitated through emitting/broadcasting events. When an update occurs in a child controller, it emits an event with data that is captured and processed by the Main Controller for updating.
MainController {

  $scope.loaded = DataService.get();
  $scope.userOptions = {};
  $scope.$on('update',function(){
   updateUserOptions();
  })
}

ChildController {

  $scope.loaded.then(function(){
    //all logic of child controller
  }

  $scope.onselect = function(){
    $scope.$emit('update',data);
  }
}

Some questions to consider:

  1. Is utilizing events between controllers considered good practice?
  2. Is attaching promises to scope beneficial for child controllers?
  3. Would incorporating services improve the code structure?

Answer №1

Based on my personal experience, I recently took on the task of revamping the architecture of a single page application that I developed.

Here are some insights from my experience:

  1. Is it beneficial to use events between controllers? In my opinion, utilizing events is a versatile approach to sharing information between controllers, even when they have isolated scopes (using methods like $broadcast or $emit). This strategy follows the Observer design pattern. Alternatively, services can also be used instead of events for data sharing. It's important to exercise caution when using $rootScope, as all $scopes inherit from it.
  2. Is it advisable to attach promises to scope for child controllers? Understanding how scope inheritance works is key in handling this issue without running into property shadowing in JavaScript. Transferring logic from scope.loaded within ChildController to a service like
    ChildService</code would contribute to better code organization and facilitate reusability. Segregating business logic through services rather than controllers aligns with good design principles.</li>
    <li><em>Will incorporating services enhance my code quality?</em> Refer back to my previous response regarding this question.</li>
    </ol>
    
    <p>To further bolster the architecture, I delved into the angular style guide authored by John Papa, which provided valuable insights.</p>
    
    <p>I suggest the following modifications:</p>
    
    <ol>
    <li><em>To ensure data loading, I utilize promises attached to scope. However, I propose emitting a custom 'loaded' event from MainController using <code>$scope.$emit('loaded')
    . Subsequently, I advocate utilizing
    $scope.$on('loaded', function(){})
    in ChildController to manage the event.
  3. Transfer the updateUserOptions function to a service and only inject it into the necessary controllers.

Hopefully, these suggestions prove to be useful!

Answer №2

Is it recommended to utilize events for communication between controllers? While not ideal for primary data sharing, events can be used to notify about system events like when data is ready.

Would using promises attached to scope for child controllers be beneficial? It's advised against due to the potential for causing various issues related to scope inheritance.

How can implementing services enhance my code? Implementing services can definitely improve the structure and efficiency of your code.

If I were in your position, here's what I suggest:

Create a dataService - responsible for managing all incoming and outgoing data. This service caches data upon request (saving the promise is sufficient) and broadcasts a 'dataReady' event via $rootScope whenever new or refreshed data is available. Controllers and other subscribers can listen for this event to retrieve the updated data. Additionally, the dataService handles data updates and can broadcast events via $rootScope when data changes occur, prompting subscribers to query the service for updated information.

Utilize directives over controllers - use directives with isolated scope to pass data between them through attributes. By doing so, you ensure that each directive receives only the necessary data instead of everything. Directives can communicate with one another using attributes, services, broadcasting/emitting events, or requiring their parents/siblings if they closely collaborate.

Answer №3

  1. Is it advisable to utilize events between controllers?

Avoid using events between controllers as it will be phased out by Angular JS 2.0. Additionally, relying on events often results in a convoluted mess of interactions that are difficult to comprehend and troubleshoot. Instead, opt for utilizing services to share data between controllers. By injecting the same service into multiple controllers, the service can store the data, allowing the controllers to bind to it and stay automatically synchronized. I have elaborated on this concept in a blog post.

  1. Is it recommended to attach promises to scope for child controllers?

Avoid attaching promises to scope for child controllers. It is more preferable to use promises and resolve data within services. Refrain from using $scope altogether and instead embrace the controllerAs syntax. The usage of $scope was deprecated even in Angular JS 1.X due to the various issues related to scope inheritance.

  1. Will incorporating services enhance my code quality?

Absolutely! Leveraging services for all logic and data manipulation is highly beneficial. Reserve controllers solely for UI interactions and delegate other tasks to services. Additionally, consider utilizing ui-router for effectively managing the state of your application.

Answer №4

Instead of directly answering your questions, I have some additional comments to share. In my opinion, the approach you mentioned may not be the most effective way to build angular applications.

  1. Placing all common logic in the Main Controller and separating other options into different controllers as children of the main controller.

It is advised against by angular style guides to include common logic in controllers. Controllers should strictly focus on view-related logic such as data binding and validation. By reducing the amount of code within a controller, you enhance reusability. Moving more logic into services results in a more scalable application.

Solution: My suggestion is to create a service for fetching data from the server and then inject this service into controllers when needed. This method also improves dependency management by clearly identifying which controllers require specific services.

  1. Avoid nesting controllers whenever possible, as Angular monitors all active scopes and reevaluates them during each $apply() loop.

Solution: Refer back to #1 and utilize services instead of relying heavily on the main controller.

  1. Implementing promises attached to scope to ensure data is loaded, signaling to child controllers that the data is available.

Utilizing promises for data retrieval is a good practice, but it is cleaner to store them in a service rather than the main controller.

  1. Moving the data updating functionality of all child controllers to the main controller due to all updates occurring in one object.

Child controllers using emit/broadcast to communicate with the main controller. When an update occurs, a child will emit an event containing data that the main controller captures to perform the update.

Solution: Opt for a service with an update function over events. Events are more challenging to debug and manage, requiring event handlers to be unregistered upon controller destruction. Using functions/promises rather than events is typically a more reliable approach.

Answer №5

Is it advisable to utilize events between controllers?

An issue with your current setup is that it relies implicitly on the hierarchy of your controllers, as the event emitted can only be caught by scopes higher up in the hierarchy. This not only creates an implicit connection that developers need to remember but also limits the extensibility of this feature.

Alternatively, injecting a shared service into all required controllers would make the connection between controllers explicit and documented, making their positions in the hierarchy independent. This approach would simplify the maintenance of your architecture and make testing easier as well.

You could still implement an observer pattern using a service.

Is it recommended to use promises attached to scope for child controllers?

The concern about polluting scopes mentioned in other responses is valid. It's better to limit the number of objects attached to your scope and utilize objects as bundles of variables instead of directly attaching all variables to the scope. (For more insights on this, refer to discussions on "always having a . in your bindings".)

(Of course, avoid bundling variables blindly just to reduce their number; try to identify meaningful semantic connections between variables that can be bundled together.)

Will incorporating services enhance my code quality?

Based on the aforementioned responses, the answer seems to be yes. There are additional benefits as well, but due to space constraints here, I won't delve into them now.

In conclusion, the issues pointed out above may not be major concerns in your current code base, but if you aspire to have the best possible architecture, there is certainly room for improvement.

Answer №6

Responses:

  1. Sorry, but it's on its way to becoming obsolete.

  2. The $scope feature is already outdated.

  3. Using services is highly recommended. They offer the flexibility to share data and functionality among different components such as controllers.

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 can I intercept/manage the back button of the browser in React-router?

Utilizing Material-ui's Tabs, which are controlled, I am implementing them for (React-router) Links in the following manner: <Tab value={0} label="dashboard" containerElement={<Link to="/dashboard/home"/>}/> <Tab value={1} label="users ...

Issue with Material-UI tab when using a datatable within it's content

I implemented the Simple Tabs feature from Material-UI with a Tab containing a Datatable using React-Data_Table. However, I noticed that this particular tab is not responsive like the others when the table is full. Empty Full Here's a snippet of th ...

jQuery AJAX File Upload problem in Internet Explorer

Encountering an issue with Internet Explorer While this script with AJAX and jQuery functions perfectly in other browsers, it fails to do so in IE index.html <form enctype="multipart/form-data" method="post"> <input name="file" type="file" ...

Using controllerAs in an AngularJS directive allows for multiple instances to be created, each with the

In my form, I have directives that contain identical input fields, selects, and check boxes. To handle this, I created a directive with an isolate scope and controllerAs syntax using bindToController=true. The controller has a method triggered by an ngChan ...

Inject parameters into the templateUrl property of an Angular component

In this scenario, my component object is structured as follows: var options = { bindings: { title: '<', rows: '<' }, controller: registers, templateUrl: function ($element, $attrs) { return ...

Error: Cannot call method rewriteRequestUrl in _this7._config.server in React native version 0.64.1

After diligently following all the guidelines provided at the upgrade helper for transitioning from RNv0.62 to v0.64.1, I managed to successfully install my app on the device. However, my metro bundler is encountering an obscure error that has left me perp ...

Tips on choosing JSON data to show on an HTML page

I am working with JSON data from a specific URL and I need to display only the information related to France on an HTML page. However, I am unsure of how to achieve this. Can someone please assist me? Here is my JavaScript code: // API Fetch Call const ...

Expanding a collection of text inputs on-the-fly (HTML/JavaScript)

Looking to streamline our data entry process, I am developing an app for in-house tasks. Our team will be required to input information about various "items" that correspond to multiple "categories." To facilitate this task efficiently, I'm explorin ...

Customize form input using Javascript prior to inserting into database

On my Rails form, I have a basic setup like the following: <%= form_for @song do |f| %> <p> <%= f.label :url %><br> <%= f.text_field :url %> </p> <p> <%= f.submit %> </p> <% en ...

Error encountered: Unable to invoke module in AngularJS using Karma and Jasmine

Trying to implement unit testing for my AngularJS app using Karma, but encountering an issue with the module function. Error message: First Test encountered a declaration exception FAILED TypeError: Property 'module' of object [object Objec ...

Issues with sample AJAX request functionality

Attempting to learn AJAX with a basic call. I've got a .txt file in the same directory as my HTML file. Can someone pinpoint where I may have gone wrong? Appreciate any help. <html> <head> <script type="text/javascript"> ...

Deprecated: Asynchronous XMLHttpRequest on the primary thread is no longer supported

Currently, I am working on the extjs framework. I have developed an application using extjs. However, whenever I launch the application in the browser, I encounter some warnings in the console. The warning message states that Synchronous XMLHttpRequest o ...

Why does the control skip the onreadystatechange function for the ajax object?

Just beginning my journey into web-development. Recently, I encountered an issue with a signup page I created that involves asynchronous calls to php. Upon debugging, I noticed that the onreadystatechange function is being completely skipped over. Any assi ...

Enhance your list items with images by leveraging the power of Angular Js

I am currently experimenting with incorporating country images alongside languages using Angular JS. <div ng-app class="nav"> <div></div> <div ng-controller="MainController"> {{selectedValue}} <ul> <li ng-r ...

When retrieving data from Select2, a string is being returned instead of an

I am facing a challenge with multiple <select class="searchselect"> elements in my HTML, each filled with numeric values. To initialize Select2, I am utilizing the code snippet below: $(".searchselect").select2({ ajax: { dataType ...

Exploring Firefox webpage data with JavaScript or browser extensions

Have you ever wondered if it's possible to retrieve the "Modified" information seen in Firefox when selecting "View page Info" by just using a JavaScript extension? ...

What methods are available for modifying nodes generated dynamically?

I have been on a quest for quite some time now to find a way to manipulate HTML content that has been dynamically added. Initially, I fetch a cross-domain website using getJSON: $.getJSON('http://whateverorigin.org/get?url=' + encodeURIComponent ...

The absence of an 'Access-Control-Allow-Origin' header on the requested resource prohibits access from the origin 'localhost:8080'

I have encountered this problem multiple times on various forums, but so far none of the suggested solutions have worked for me. Currently, I am developing a MEAN stack application that utilizes PassportJS for Twitter login functionality. angular.module( ...

Struggling to dynamically resize 2 boxes using JavaScript

I am attempting to create a layout with two Divs side by side, each containing slightly different content. I have successfully resized them equally using JavaScript, but the issue arises when loading the collapsed content as it does not adjust to the new s ...

What is the proper method for implementing respond_to with JSON data?

I find myself in a bit of a dilemma: I'm currently developing a centralized controller based on the guidance provided in this query and am encountering some confusion regarding the functionality of the respond_to method. In an API::Controller, my cod ...