How to synchronize $scope variables between controllers in AngularJS

As a newcomer to Angular, I have a seemingly simple question regarding setting up a comments system for articles. I've implemented two angular controllers - one for loading comments upon page load and another for submitting new comments to the server. While these functions work well individually, I'm facing issues in updating the displayed comments with the newly submitted comment within the success() method. Despite trying various methods, my current code fails to achieve this. Can someone please assist me?

I suspect the issue lies in handling different $scope variables, however, the documentation available hasn't cleared up my confusion.

article.js

// initialize app
var articleApp = angular.module('articleApp', ['btford.markdown', 'ngSanitize']);
// define controllers
articleApp.controller('DisplayCommentsCtrl', function ($scope, $http) {
    $scope.loadComments =   function () {
        $http.get(Routing.generate('article_comments', { id: window.articleId })).success(function (data) {
            $scope.comments = data.comments;
        });
    };
    $scope.loadComments();
});

articleApp.controller('SubmitCommentCtrl', function ($scope, $http, $route) {
    $scope.loadComments = function () {
        $http.get(Routing.generate('article_comments', { id: window.articleId })).success(function (data) {
            $scope.comments = data.comments;
        });
    };
    $scope.loadComments();

    $scope.formData = {
        'comment':{
            'save'      :   'Save',
            'comment'   :   '',
            '_token'    :   $('#comment__token').val()
        }
    };
    $scope.processForm = function ($route) {
        $http({
            method  :   'POST',
            url     :   Routing.generate('article_new_comment', { id: window.articleId }),
            data    :   $.param($scope.formData),
            headers :   {
                'Content-Type': 'application/x-www-form-urlencoded'
            }
        })
        .success(function (data, $route) {
            $route.reload();
        });
    };
});

article.html.twig

<div class="col-md-12">     
    <div class="commentFormContainer" ng-controller="SubmitCommentCtrl">
        {% verbatim %}
        <p>{{ formData.comment.comment }} / {{ formData.comment._token }}</p>
        {% endverbatim %}
        <!--{{ form_start(commentForm, { 'attr': { 'id': 'commentForm', 'ng-submit':'processForm()' }}) }} -->
        <form name="comment" id="commentForm" ng-submit="processForm()">
            {{ form_errors(commentForm) }}
            {{ form_row(commentForm.comment, { 'attr': { 'ng-model': 'formData.comment.comment' } }) }}
            {{ form_widget(commentForm._token) }}
            {{ form_end(commentForm) }}
    </div>

    {% verbatim %}
    <div class="articleCommentContainer"  ng-controller="DisplayCommentsCtrl">
        <div ng-repeat="comment in comments | orderBy: '-time'">
            <div class="articleCommentComment" ng-bind-html="comment.commentHTML">              
            </div>
            <div class="articleCommentDetails">
                <p>[{{ comment.creator }} @ {{ comment.time|date:'EEE d MMM, h.mm a' }}]</p>
            </div>
        </div>
    </div>
    {% endverbatim %}
</div>

Answer №1

Big shoutout to all the amazing people who took the time to comment and help me out. I was able to resolve the issue by implementing event broadcasting, which wasn't my initial plan but turned out to be a great solution. Below is the code snippet that illustrates how I tackled the problem.

In essence...

Previously, I was struggling with reloading one controller, DisplayCommentsCtrl, from another controller, SubmitCommentCtrl, or using a method defined in one controller within a different controller. However, I switched to utilizing the angular event dispatcher within the $http.success() function of SubmitCommentCtrl to trigger an event that I'm monitoring in DisplayCommentsCtrl. All the necessary information to display the comment is supplied as the argument for this event, retrieved from the data returned in the $http.success().

This approach effectively deals with scope-related issues. Since my two controllers have distinct scopes, methods defined in one couldn't be executed in the other, and changing a scope variable in one didn't impact the other. With $rootScope injected into my SubmitCommentCtrl, I can now utilize the

$rootScope.$broadcast(strEventName, mixedData)
method to broadcast to all child scopes. In DisplayCommentsCtrl, I listen for this broadcast using
$scope.$on(strEventName, function (event, mixedData) { // do something })
.

I hope this explanation proves helpful. For further insights on scopes in angular, check out: https://docs.angularjs.org/guide/scope.

article.js

// create app
var articleApp = angular.module('articleApp', ['btford.markdown', 'ngSanitize', 'ngAnimate']);

// controller to display comments
articleApp.controller('DisplayCommentsCtrl', function ($scope, $http) {
  // load comments method
  $scope.loadComments = function () {
    $http.get(Routing.generate('article_comments', { id: window.articleId })).success(function (data) {
      $scope.comments = data.comments;
    });
  };
  $scope.loadComments();

  // handle new comments
  $scope.$on('newComment', function (event, newComment) {
    $scope.comments.push(newComment);
  });

});

// controller to submit a new comment
articleApp.controller('SubmitCommentCtrl', function ($scope, $rootScope, $http) {
  $scope.loadComments = function () {
    $http.get(Routing.generate('article_comments', { id: window.articleId })).success(function (data) {
      $scope.comments = data.comments;
    });
  };
  $scope.loadComments();

  $scope.formData = {
    'comment':{
      'save': 'Save',
      'comment' : '',
      '_token': $('#comment__token').val()
    }
  };
  $scope.processForm = function ($route) {
    $http({
      method: 'POST',
      url: Routing.generate('article_new_comment', { id: window.articleId }),
      data: $.param($scope.formData),
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
      }
      })
    .success(function (data) {
      // append new comment below the form
      $rootScope.$broadcast('newComment', data);
      // clear the form
      $scope.formData.comment.comment = '';
    });
  };
});

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

Merging the outcomes of a JSON call

Presently, I have an async function that returns a JSON response in the form of an array containing two objects. Please refer to the screenshot. https://i.sstatic.net/gCP8p.png How can I merge these objects to obtain: [{resultCount: 100, results: Array(1 ...

How can I programmatically adjust the center of a Google Maps v3 map?

I have a table with 2 columns. The first column contains a div with a Google map, while the second column has a panel that changes its width after a few seconds. On the map, there is a marker placed. Issue: When I click on a button that triggers setCente ...

What is the fallback mechanism in Astro js when the cache is unavailable?

When the cache is not accessible in Next.js, the page will be server-side rendered and displayed using either the true or blocking fallback approach. I am curious about the approach taken by Astro.js in this situation. I am planning to develop a dynamic b ...

Ways to deactivate a button with a designated identification through iteration using jQuery

Can't Figure out How to Deactivate a Button with Specific ID $('.likes-button').click(function(){ var el= this; var button1 = $(el).attr('id'); console.log(button1) $('#button1').attr("disabled",true); }) ...

Tips for applying textures dynamically to MeshPhongMaterial?

When trying to apply a texture on a THREE.MeshPhongMaterial, the texture fails to load. Here's the code snippet: let earth_geometry = new THREE.SphereGeometry(450, 10, 10) let earth_material = new THREE.MeshPhongMaterial({ emissive: 0xffffff }) ...

What is the issue with undefined params in Next.js?

I have come across an issue with the function in app/api/hello/[slug]/route.ts When I try to log the output, it keeps showing as undefined. Why is this happening? The code snippet from app/api/hello/[slug]/route.ts is shown below: export async function G ...

What are the best practices for implementing angular js routing alongside laravel/lumen routing?

I am currently working on a web application built with the latest version of Laravel (5.*). Despite conducting extensive research, I have not been able to find a precise solution for incorporating AngularJS routing with Laravel routing. Consider URLs like ...

Displaying information on an Angular user interface grid

I am facing an issue with displaying data in a UI grid table. I have set up an API through which I can access the data in my browser, but I am encountering difficulties when it comes to rendering the data. Below is my Angular controller where I have defin ...

What is the best way to manage feedback on various posts?

I am struggling to retrieve individual posts as it appears that I am only able to access the first one. Is there a way to uniquely identify each post using PHP and then retrieve the same value with JavaScript? Alternatively, I am open to any other solutio ...

Issues arising with transferring information between components

My webpage had a header with a search engine input, a list of posts, and pagination all on one page. I made the decision to separate the header into its own component in a different Vue file. However, after making this change, searching for posts by their ...

Can JQuery's 'unslider' be customized to only change the backgrounds?

Check out my source at this link: http://codepen.io/anon/pen/Bvkjx Observe how the content and background images rotate correctly. Now, I'm curious if it's feasible to keep the following content static <p>SOME CONTENT1</p> while ...

Avoid reloading the header component along with its APIs when navigating routes in React JS

I'm currently working on a web application using react js/next js and within it, I have various pages that make use of globally shared components like the Header and Footer. However, I am facing an issue where I want to prevent unnecessary re-renders ...

Issue with displaying options in Angular2 v2.4.9 HTML select element

Ever since I made the transition from AngularJS to Angular2, I've been facing a peculiar issue. The select element's options data is fetched from a Solr query, which always returns a 200 response with the data in a timely manner. However, the pr ...

Caution: A duplicate key was found in ReactJS when attempting to flatten children

Currently, I am utilizing Tabs from Material UI to showcase a List component that is filtered by the tab. Take a look at the code snippet below from my Container Component: <Tabs className="DrawerTabs" ...

Tips for consolidating all functions into a single file for ReactJS inheritance:

I'm curious about something. In Angular JS, we have the ability to create a global service file that can be inherited by every component. This allows us to use the functions written in the global service file within each respective component. Is ther ...

Why won't JSZip accept a base64 string for loading a zip file?

As I work on implementing a feature where a small JSON object is written to the URL as a user interacts with items on a page, I also want to make sure the URL can be read later so users can resume where they left off. I successfully managed to create the ...

Organizing data in a database the arrangement way

I'm looking to populate an array with values for "name" and "nickname" extracted from an SQLITE database and then display them in an alert box. This task is part of a JavaScript project developed using Titanium Appcelerator. Below is the code snippe ...

divide a single item into several items depending on its attribute

data = {1-inputWidth : '30px' , 1-inputHeight: '30px', 1-color : 'red', 2-inputWidth : '20px' , 2-inputHeight: '10px', 2-color : 'blue', 3-inputWidth : '60px' , 3-inputHe ...

Utilize emit to distribute / allocate a variable

I have some variables stored in a file called server.js (and they tend to change frequently). My goal is to pass these variables to client.js whenever the client sends a request (triggers the 'validate' event). Even though the event is triggered, ...

Top strategies for managing fixed datasets

Imagine having a dataset containing country names and their corresponding phone prefixes, like so: var countryPhonePrefixes = [ { 'name': 'Germany', 'prefix': '+49' }, { 'nam ...