Angular view fails to update after form submission when using ngDialog to change the scope

After starting my Angular journey, I decided to challenge myself by creating a comprehensive todo app for educational purposes. I seem to be missing something pretty basic, although I can't quite put my finger on it. It seems like there might be an issue with how I've set up my controllers and templates. Despite trying some suggestions from similar queries, none have resolved my problem. Even attempting to use $scope.$apply() leads to the dreaded "apply/digest already in progress" error.

My setup involves ngRoute so that when a user visits /profile, it triggers the profileController and loads templates/profile.html. The sole purpose of this controller is to establish the current user and attach to $rootScope. Within the profile view, I've included a nested controller named listController. This controller receives the List resource to handle HTTP requests. Everything appears to function correctly regarding routing and GET/POST requests.

Below, I've provided a simplified version of my controller:

var myApp = angular.module('todo', ['ngRoute', 'ngResource'])
    // config stuff...
    .controller('listController', ['$scope', 'List', 'ngDialog', function ($scope, List, ngDialog) { 
        // Fetches all lists associated with the current user
        $scope.lists = List.query();

        // Function to open modal form
        $scope.openModal = function () {
            ngDialog.open({
                template: 'templates/partials/new-list.html',
                className: 'ngdialog-theme-default'
            });
        };

        $scope.createList = function () {
            List.save({}, {
                name: $scope.list.name,
                description: $scope.list.description
            }).$promise.then(function(result) {
                $scope.lists.push(result);
            });
        };
    }]);

The snippet below represents the relevant section of templates/profile.html, which successfully displays all lists fetched using List.query():

<div class="todo-sidebar" ng-controller="listController">
    <h3>Your lists <a href="#" ng-click="openModal()"><span>New list</span></a></h3>
        <ul>
            <li ng-repeat="list in lists">
                <a href="#"><span class="list-name">{{list.name}}</span></a>
        </li>
    </ul>
</div>

The issue arises when I invoke the createList function from the templates/partials/new-list.html partial:

<div class="dialog-contents" ng-controller="listController">
    <h3>New list</h3>
    <form ng-submit="createList()">
        <div class="form-group">
            <label>Name</label>
            <input type="text" name="name" ng-model="list.name">
            <textarea name="description" ng-model="list.description" rows="10"></textarea>
            <button type="submit" class="button">Create list</button>
        </div>
    </form>
</div>

While the form submission works flawlessly and adds the new list to the database, the view doesn't update in real-time. Upon inspecting with console.log($scope) within the promise block, it's apparent that the new list does get appended to the scope.

I suspect that attaching a controller to multiple elements/templates may not be best practice, but I'm unsure about alternative structuring options.

Answer №1

After conducting some research, I believe I have found a solution to your issue. It appears that the problem lies in how you are handling the closure of the dialog box.

Below is the link that I referred to during my research:

https://github.com/likeastore/ngDialog#api

Scope Problem

The issue at hand seems to be related to scope. When the dialog box opens, it creates a separate module with its own controller. This controller's scope is one-way bound and cannot be accessed by the parent scope when the dialog resolves. This explains why your scope is not updating at the parent level.

For more information on resolving this issue, please refer to the section about promises.

Promise Solution

To manage the scope at the parent level, you will need to use a promise function. This function executes after the dialog closes completely. By utilizing the promise function, you can pass data and update the parent-level scope variables accordingly.

I have provided updated code below that may assist you in addressing this problem:

var myApp = angular.module('todo', ['ngRoute', 'ngResource'])
// config stuff...
.controller('listController', ['$scope', 'List', 'ngDialog', function ($scope, List, ngDialog) { 
    // Retrieve all lists for the current user
    $scope.lists = List.query();

    // Function to open modal form
    $scope.openModal = function () {
        var dialog = ngDialog.open({
            template: 'templates/partials/new-list.html',
            className: 'ngdialog-theme-default',
            controller : function($scope){  
                $scope.createList = function(){
                    dialog.close($scope.list); // Pass list data when closing dialog
                };
            }
        });
        dialog.closePromise.then(function(data){
            // Update value based on data passed from dialog closure
            List.save({}, {
               name: $scope.list.name,
                description: $scope.list.description
            }).$promise.then(function(result) {
               $scope.lists.push(result);
            });
        });
    };
}]);

This code serves as a general guideline for implementing the solution. Feel free to reach out if you require further clarification or assistance. Good luck!

Answer №2

It seems like you may be experiencing a $scope issue. While the values are present, it appears that you're not referencing them correctly. Try accessing the "lists" using controllerAs, as shown below:

<li ng-repeat="list in MyController.lists"> 

This adjustment should resolve your issue.

I hope this solution proves helpful to you. For a more in-depth explanation, you can also refer to this resource: https://github.com/angular/angular.js/wiki/Understanding-Scopes#ngRepeat

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 prevent an empty iframe from triggering a load event upon injection

I have implemented a technique where I am using an empty frame to handle pseudo-asynchronous form submission. This involves referencing the frame's name attribute in the form's target attribute, allowing the form's action URI to resolve in t ...

Setting up a simple configuration for WebGl and Javascript

I am currently using OSX 10.9.5 (Mavericks) and following a WebGL tutorial script provided on . I copied and pasted the code from the tutorial into TextEdit and saved it as HTML with the following file structure: webgl | +--index.html | ...

"Following successful POST login and session storage in MongoDB, the session is unable to be accessed due

When sending login data by POST with the credentials: 'include' option from client server 5500 to backend server 3000, I ensure that my session data is properly stored in MongoDB thanks to the use of 'connect-mongodb-session'. In the ba ...

Asynchronous Return in NodeJS Class Methods

Currently, I am in the process of developing a JavaScript class that includes a login method. Here is an overview of my code: const EventEmitter = require('events'); const util = require('util'); const Settings = require('./config ...

Using CSS in combination with AngularJS, you can create a dynamic growth effect for a div element that initially

I am currently using AngularJS to dynamically add divs to a section. My goal is to have each div start with a static width and then grow dynamically as I continue to add more divs. How can I achieve this? The following code is not producing the desired re ...

Tips for adjusting the dimensions of a map within the app.component.html

Within the code snippet below, my aim is to adjust the width and height of the map using the style tag shown here: <style> #map3 .map { width: 100%; height:90px; } </style> Despite trying various values for width an ...

What is the best way to incorporate a particular locale from AngularJS I18n files with bower?

After successfully downloading the angular I18n repo by using bower install angular-i18n, it is now located in my bower_components directory and has updated the bower.json file with angular-i18n : 1.5.3 as expected. However, I am facing an issue where a s ...

Adjusting the size of an object as the page dimensions change

I am looking to dynamically resize an element whenever the document resizes. For example, if a draggable div is moved and causes the document to scroll, I want to adjust the size of another element using $("#page").css('height','120%'); ...

typescriptUsing redux: prevent parent component from accessing redux props

I'm currently using redux and typescript in my webapp project. What's the best approach for defining props in a component that receives redux-actions through @connect, as well as props from its parent? // mychild.tsx export namespace MyChildCom ...

Placing buttons on top of a video within a div container

I am facing a challenge with implementing custom controls on a video embedded in my webpage. I have tried setting a div to absolute position for the buttons, but they are not clickable. Is there a way to achieve this without using jQuery? I need the butto ...

Turning JSON data into an array format, omitting the keys

Can someone help me with a query that will retrieve a specific column from the database and return it in this format: [ { "tenantName": "H&M" }, { "tenantName": "McDonalds" } ] I would like to transform ...

Angular Automatically Generated Identifier for Event Detection

By using jQuery, I can easily target an ID that starts with "conditionValue" $(document).on('focus', "[id^=conditionValue]", function (event) { // code }); But how can I achieve the same in Angular when looking for an ID starting with somet ...

How to fetch a single document from a nested array using Mongoose

Currently, I am working on a MongoDB database using Mongoose in Node.js. The collection structure resembles the following: { cinema: 'xxx', account: 'yyy', media: { data: [{ id: 1, name: 'zzz& ...

Using `getElementById` within the Vue.js `mounted` lifecycle hook can sometimes return null

Every time I attempt to retrieve the contents of an id using document.getElementById, I keep receiving a value of null. Below is a snippet of the code: <input-layout v-if="edit" label="Status" class="grayout"> &l ...

Ways to dynamically update a div with data from a JSON response

I'm currently in the process of developing a search platform. I have three static divs on the search results page that display certain content, all containing similar code. For example: <div id="result" class="card"> <img src="hello.png" ...

Implementing child components in React using TypeScript and passing them as props

Is it possible to append content to a parent component in React by passing it through props? For example: function MyComponent(props: IMyProps) { return ( {<props.parent>}{myStuff}{</props.parent>} } Would it be feasible to use the new compone ...

Is there a way to navigate to a specific div when clicking on it?

Need help with scrolling after running code function scrollFunction() { document.getElementById('insert').scrollIntoView(); } I have a button that triggers some code and I want the page to scroll afterwards. Currently, it scroll ...

Determining which data is retrieved from a database based on a specific field using Sequelize and MySQL

I'm looking to retrieve the most recent records from a database, organized by category. My goal is to fetch 20 records, with 5 of the latest posts in each category. I want to ensure that the result consists of 20 total records, evenly distributed amon ...

Occasionally, there are instances when node.js combined with express.js and hogan.js may result in a blank page being

Most of the time, every feature in this app functions properly. However, there are instances when a blank page is displayed instead of the homepage (or any other page). Interestingly, making a minor adjustment to the affected view, such as adding a space o ...

Utilize dynamic directive naming within the AngularJS framework

My dataset consists of various data types with corresponding directives attached to each one. text email audio video image Currently, logic is in place using if/else statements to call the appropriate directive based on the data type. Is there a way to ...