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

What are some ways to keep text within the boundaries of a div element?

I have tried multiple solutions for this issue, but none seem to be working for me. When I append a paragraph to a div, the text extends beyond the element. Below is the code I am using. Any assistance would be greatly appreciated. CSS: .chat-h { margi ...

What would you name this particular element?

I want to create a unique slider design but I'm unsure where to begin or how to search for information because I don't know the correct terminology. Does this type of slider have a specific name? I heard about Marquee, but that seems like someth ...

Mastering the art of utilizing AJAX for autocomplete functionality

While utilizing the autocomplete feature from jqueryui (http://jqueryui.com/autocomplete/#remote) and fetching data from "source: "search.php"" The following script ... $( "#name" ).autocomplete({ source: "search.php", minLength: 2, select: function( ...

The concept of IFA on Android and accessing it through the browser/javascript

IFA (Identifier for Advertisers) is a new feature in iOS 6 that functions as a unique ID for tracking user context anonymously and improving the overall experience. My inquiries mainly focus on the realm of web development (specifically mobile browser/jav ...

Storing HTML table data in a MySQL database will help you

Operating a website focused on financial planning where users can input various values and cell colors into an HTML table. It is crucial to uphold the integrity of these HTML tables. How can I store the complete HTML table (including values and colors) i ...

JavaScript in Internet Explorer is showing an error message stating that it is unable to access the property '0' of an undefined or null

JavaScript Code function update() { var newAmt = 0; var newtable = document.getElementById("tbl"); for ( var i = 0; i < newtable.rows.length; i++) { innerTable = newtable.rows[i].cells[0].childNodes[0]; if ( (innerT ...

Tips for resolving issues with storing data in a text box that is constantly being added to

Can someone please assist me with this issue I'm facing? I am using isset to check if the index is defined, but it stores 0 instead of saving the value of the textbox. How should I tackle this problem? If I don't check if the index is defined and ...

Obtaining a string from a regular expression does not function as anticipated

Currently, I am in the midst of a project that requires me to identify specific HTML tags and replace them with others. To accomplish this task, I am utilizing JavaScript, and the code snippet looks like this: // html to update html = '<div cla ...

Repeated module imports

Currently, as part of my app development process, I am utilizing Parcel along with @material-ui/styles. One crucial aspect to note is that my app has a dependency on the @material-ui/styles package. Additionally, I have incorporated my own npm package, sto ...

Getting the value of a button using JavaScript

Is there a way to retrieve the value of a button when multiple buttons are generated dynamically? I have a JavaScript function that creates buttons in a list based on my search history, with each button labeled as a city name. However, after clicking on o ...

The error message "Element is not defined (Object.<anonymous>)" is occurring in the context of Intro.js-react, React, Next.js, and Tailwind

Here is a code snippet: import { useState } from 'react'; import { Steps } from 'intro.js-react'; export default function Dashboard() { const [stepEnabled, setStepEnabled] = useState(true); const steps = [ { intro: &apos ...

What is causing this to function properly only during the initial display of the dialog?

When using ui-bootstrap with the attribute attached to the ok/save button on the dialog, I encountered an issue. The first time my dialog is created, it focuses on the button just as expected. However, every subsequent time it has no effect. .directive(&a ...

Leveraging JavaScript to identify web browsers

I am looking to implement a feature on my website where if the visitor is using Internet Explorer 8.0 or an earlier version, they will receive an alert prompting them to upgrade their browser before proceeding. For users with other browsers, the page will ...

Utilizing distinct AngularJS controller files within a Laravel&Angular collaboration project

I attempted to implement this solution: However, I encountered the following error: GET http://localhost:8000/js/TaskController.js net::ERR_ABORTED 404 (Not Found) Afterwards, I explored another solution: https://github.com/angular/angular-cli/issues ...

Implementing an asynchronous task queue in AngularJS

I came across this JSFiddle example where three consecutive calls are made to a service function, simulating $http Request interceptor function which returns a promise. The current code does not wait for the previous call to finish before making the next o ...

The readStream in Node.JS unexpectedly terminates before the writeStream

I'm currently working on a project that involves fetching PDF files from remote servers and immediately sending them back to the clients who made the request. Here is the code snippet I am using: var writeStream = fs.createWriteStream(filename); writ ...

Angular allows for the creation of dynamic and interactive scenes using Canvas and Three.js

I am in the process of developing a collection of web apps within an Angular SPA. Each individual application is encapsulated within an Angular template, and when navigating between them, specific DOM elements are replaced and scripts from controllers are ...

In which part of my code should I implement the string to numerical function for my OrderBy function?

I successfully implemented a sortable header for my table with no errors, everything is functioning as expected. However, there is a small issue that I anticipated beforehand. The data in my JSON is string-based with numerical values that include symbols l ...

What are the differences between incorporating JavaScript directly into HTML and writing it in a separate file?

I need help converting this JavaScript embedded in HTML code into a standalone JavaScript file. I am creating a toggle switch that, when clicked, should go to a new page after the transformation. I am looking for the non-embedded version of the function. H ...

Is your Angular2 form page experiencing reloading issues?

I am currently incorporating Angular2 into my project. I am facing an issue where the page keeps refreshing, and I'm unable to determine the cause. Below is a snippet of my form: <form> <div class="form-group"> ...