Angular's ng-submit directive does not use the most up-to-date scope available

I'm currently learning Angular and have been struggling with a particular issue.

I have created a form to edit user details. Upon page load, I make an AJAX call to fetch the data of the selected user and populate the scope with the values. Initially, I can see these values in the input fields.

The problem arises when I click submit using ng-submit with a function that packages the JSON data before sending it off. Inside this function, the $scope does not reflect the changes...

To test whether two-way binding is functioning correctly, I added an expression in the DOM and confirmed that the value was updating in real time.

I've been unable to figure out the issue. Here's the code:

HTML:

<div class="view-container">
        <!-- HTML code goes here -->
      </div>
    

JavaScript:

(function ( window, angular ) {
        // JavaScript code goes here
    })( window, angular )
    

Answer №1

Appreciate the help @user2881430

Certainly, I managed to resolve the issue by utilizing ng-model="formData.data" and passing formData to the ng-submit function.

Below is the snippet of code:

HTML:

<div class="view-container">
    <div class="view-container__container" id="users-view">
        <header class="view-container__header">
            <h1>New User</h1>

            <div class="view-container__actions">
                <button type="submit" form="user" class="btn btn--outline" ng-disabled="user.$invalid">Save</button>

                <div class="view-container__actions-critical">
                    <a href="#/user-management" class="btn btn--delete">Discard Changes</a>
                </div>
            </div>  
        </header>

        <div class="view-container__content">
            <div class="flash flash--{{ flash.type }}" ng-show="flash.display">
                <p class="flash__title">{{ flash.title }}</p>
                <ul class="flash__description">
                    <li ng-repeat="message in flash.message">{{ message }}</li>
                </ul>
            </div>

            <form name="user" id="user" class="form form--white" ng-submit="processForm(formData)" novalidate>

                <fieldset class="form__group">
                    <fieldset class="row">
                        <fieldset class="col-sm-6">
                            <label for="firstName">First Name <span class="form__required">*</span></label>

                            <div ng-messages="user.firstName.$error" ng-show="user.firstName.$invalid">

                                <small class="form__error" ng-message="required">
                                    This field is required.
                                </small>
                            </div>

                            <input type="text" id="firstName" name="firstName" ng-model="formData.firstName" required>
                        </fieldset>

                        <fieldset class="col-sm-6">
                            <label for="lastName">Last Name <span class="form__required">*</span></label>

                            <div ng-messages="user.lastName.$error" ng-show="user.lastName.$invalid">

                                <small class="form__error" ng-message="required">This field is required.</small>
                            </div>

                            <input type="text" id="lastName" name="lastName" ng-model="formData.lastName" required>
                        </fieldset>
                    </fieldset>

                    <fieldset class="row">
                        <fieldset class="col-sm-6">
                            <label for="email">Email <span class="form__required">*</span></label>

                            <div ng-messages="user.email.$error" ng-show="user.email.$invalid">

                                <small class="form__error" ng-message="required">This field is required.</small>
                                <small class="form__error" ng-message="email">Please enter a valid email.</small>
                            </div>

                            <input type="email" id="email" name="email" ng-model="formData.email" required>
                        </fieldset>
                    </fieldset>
                </fieldset>

                <fieldset class="form__group">
                    <h2>Password Reset</h2>

                    <fieldset class="row">
                        <fieldset class="col-sm-6">
                            <label for="oldPassword">Old Password <span class="form__required">*</span></label>

                            <!-- <div ng-messages="user.oldPassword.$error" ng-show="user.oldPassword.$invalid">
                                <small class="form__error" ng-message="required">This field is required.</small>
                            </div> -->

                            <input type="password" id="oldPassword" name="oldPassword" ng-model="formData.oldPassword"></input>
                        </fieldset>
                    </fieldset>

                    <fieldset class="row">
                        <fieldset class="col-sm-6">
                            <label for="password">New Password <span class="form__required">*</span></label>

                            <!-- <div ng-messages="user.password.$error" ng-show="user.password.$invalid && user.password.$touched || user.password.$dirty">
                                <small class="form__error" ng-message="required">This field is required.</small>
                                <small class="form__error" ng-message="minlength">Please enter a password that contains a minimum of 6 characters.</small>
                            </div> -->

                            <input type="password" id="password" name="password" ng-model="formData.password" ng-minlength="6"></input>
                        </fieldset>

                        <fieldset class="col-sm-6">
                            <label for="confirmPassword">Confirm New Password <span class="form__required">*</span></label>

                            <!-- <div ng-messages="user.confirmPassword.$error" ng-show="user.confirmPassword.$invalid && user.confirmPassword.$touched || user.confirmPassword.$dirty">
                                <small class="form__error" ng-message="required">This field is required.</small>
                                <small class="form__error" ng-message="minlength">Please enter a password that contains a minimum of 6 characters.</small>
                                <small class="form__error" ng-message="compareTo">Your passwords do not match.</small>
                            </div> -->

                            <input type="password" id="confirmPassword" name="confirmPassword" ng-model="formData.confirmPassword" ng-minlength="6" compare-to="password"></input>
                        </fieldset>
                    </fieldset>
                </fieldset>
            </form>
        </div>
    </div>
</div>

JavaScript:

(function ( window, angular ) {
    let EditUserController = ( $scope, $http, $routeParams, $cookies, Flash ) => {
        $scope.formData = {} // initializing form data as empty
        $scope.csrf = $cookies.get( 'csrf-token' )
        $scope.name = `${$scope.firstName} ${$scope.lastName}`

        let onError = err => {
            Flash.display({
                type: 'error',
                title: 'Oops... An error occured. Please try again later.',
                message: err
            })

            console.error( err )
        }

        let getUserSuccess = data => {
            // merge server response data with form data for updating values
            angular.extend( $scope.formData, data )
        }

        let patchUserSuccess = () => {
            Flash.display({
                type: 'success',
                title: 'Success!',
                message: `${$scope.name} was successfully saved.`
            })

            window.location.hash = '#/user-management'
        }

        let patchUser = data => {
            $http({
                method: 'PATCH',
                url: `/admin/user/${$routeParams.id}`,
                data: data,
            })

            .success( res => {
                if ( !res.success ) onError( res )
                else patchUserSuccess()
            })

            .error( onError )
        }

        $scope.processForm = ( formData ) => {
            // include csrf token for security
            angular.extend( formData, { _csrf: $scope.csrf })
            patchUser( formData )
        }

        $http({
            method: 'GET',
            url: `/admin/users/${$routeParams.id}`
        })

        .success( res => {
            if ( !res.success ) onError( res.error )
            else getUserSuccess( res.data )
        })

        .error( onError )
    }

    angular
        .module( 'app' )
        .controller( 'EditUserController', [
            '$scope',
            '$http',
            '$routeParams',
            '$cookies',
            'Flash',
            EditUserController
        ])
})( window, angular )

I'm still intrigued about the reason behind the out-of-sync behavior with $scope...

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

Modify the ColVis Appearance in Datatable Using JavaScript

Where can I modify the background color for the 'Hide/Show columns' label in the ColVis.js file? ...

Storing information within a Express application using Postgres

Recently, I've been delving into the world of Express and experimenting with a program that allows users to create events and invite others. While I know about using join tables to retrieve data, I'm curious if there's a way to organize the ...

What is the best choice for UI design framework when creating an ERP web application?

I am in the process of creating a web-based ERP application using Angular Material. However, I've noticed that each input element takes up a significant amount of vertical space on the page. This means if I have 15 input elements, I have to scroll dow ...

Will there ever be a possibility in the future to compile from D 2.0 to Javascript?

An experienced C++ programmer (that's me) is venturing into other programming languages and considering the value of learning more about D 2.0. The clean, fresh rewrite of D has caught my eye with its pragmatic and wise choices. Now, I'm eager to ...

Quantify the Proportion of Affirmative/Negative Responses and

I am attempting to calculate the percentage of "Yes" or "No" responses in an HTML table based on user input for each month's questions. Then, I want to display the average percentage in the "average" column for each month. For example, if the user sel ...

Angular 5 arrays within arrays

I'm currently facing an issue with using ngFor on a nested JSON output. The outer loop is working as expected, but the inner loop is not functioning properly. Below is my code snippet: Typescript file import { Component, OnInit } from '@angula ...

What's the best way to group rows in an angular mat-table?

I am working on a detailed mat-table with expanded rows and trying to group the rows based on Execution Date. While looking at this Stackblitz example where the data is grouped alphabetically, I am struggling to understand where to place the group header c ...

Creating components in reactjs using the render function

Just a quick query – I've been diving into react js recently. Typically, when we create a component in React, we include the HTML template within the render function. I've noticed that most examples consist of small components with minimal HTM ...

Error: 'callback is not a function' when using function.apply()

Why is this not working as expected? The error message indicates that typeof(callback) is undefined. function A(a, callback) { document.write(typeof(callback)); callback(); return a; } function Run(func, args) { return func.apply ...

The placement of Bootstrap Datepicker is experiencing issues

I have integrated the Bootstrap Datepicker from Eternicode into my ASP.Net MVC website. While the functionality is working well, I am facing difficulty in positioning the datepicker modal using the orientation option mentioned in the documentation and code ...

Sweet treats, items, and data interchange format

Can an object be converted to a string, stored in a cookie, retrieved, and then parsed back to its original form when the user logs on again? Here's a concise example of what I'm asking: var myObject = { prop1: "hello", prop2: 42 }; va ...

What is the best way to integrate a PHP page with its own CSS and JavaScript into a Wordpress page?

I'm facing a challenge with integrating a dynamic PHP table into my WordPress page. Despite working perfectly when opened locally, the CSS and JavaScript used to create the table are not functioning properly when included in a WordPress page via short ...

Currently dealing with a script that utilizes AJAX GET to incorporate JSON data into my table

Greetings and thank you for taking the time to read this! Within my HTML, I have implemented a form element that allows inputting data into 5 different fields. This data is then transmitted to a database using my unique API key. Once stored in the database ...

Having trouble obtaining search parameters in page.tsx with Next.js 13

Currently, I am in the process of developing a Next.js project with the Next 13 page router. I am facing an issue where I need to access the search parameters from the server component. export default async function Home({ params, searchParams, }: { ...

I'm puzzled as to why my Vuex modules are not functioning properly. I keep receiving the error message: "[vuex]

I've been searching for hours and can't figure out why I keep getting this error message: [vuex] unknown mutation type: groceryStore/getStoreApple on all of the commits to the mutations in the groceryStore-module. I believe I'm following the ...

What methods can we employ to prevent the GraphQL query from being triggered with every keystroke when using React?

Recently, I received a new task that requires me to implement input value debouncing to prevent backend requests on every keystroke. Additionally, I need to establish an internal useState for CollectionsAutocomplete, which is connected to the generalQuery ...

Is there a way for me to retrieve $event within a directive?

I'm struggling to figure out how to pass it as an attribute! Although I can use ng-click="function($event)" to pass $event to a controller function, I really want to access it within a directive. My main goal is to be able to stopPropagation() and/o ...

"Exploring the possibilities of RSelenium and Javascript together

While I have a strong understanding of R, my knowledge in javaScript and other languages is very limited. My goal is to access information from a publicly-available data set found here: . Specifically, I have a list of postal codes formatted as 'A1A1A ...

Customizing animations for birds

I'm currently in the process of developing a new website. The link to access the site is: One thing I am eager to achieve is having birds from this specific link incorporated into my background: I have attempted various methods without success. If a ...

Should the use of readFileSync() during the initialization of a Node.js web application be avoided?

I have a Node app that serves web pages with static HTML-snippet files included conditionally. I am considering implementing a cache map for these snippets by adding the following code to my Express's app.js file: var cache = Object.create(null); cac ...