0

我是 Angular 的新手,我在这个问题上已经有一段时间了。

我有一个表格来编辑用户。当页面加载时,我执行 AJAX 调用以从所选用户获取数据并将值添加到范围。此时,我看到了输入中的值。

当我单击提交时,我正在使用ng-submit一个在发送 JSON 之前将其打包的函数。问题是在该函数内部,$scope不包含更改...

为了测试双重绑定是否有效,我在 DOM 中放置了一个表达式,我可以看到该值完全同步。

我想不通......这是代码:

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()" 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="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="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="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="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="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="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.id = ''
        $scope.firstName = ''
        $scope.lastName = ''
        $scope.email = ''
        $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 => {
            $scope.id               = data._id
            $scope.firstName    = data.firstName
            $scope.lastName     = data.lastName
            $scope.email            = data.email
        }

        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 = () => {
            debugger

            let data = {
                _csrf:          $scope.csrf,
                id:                 $scope.id,
                firstName:  $scope.firstName,
                lastName:   $scope.lastName,
                email:          $scope.email
            }

            if ( $scope.password || $scope.oldPassword || $scope.confirmPassword ) {
                data.password               = $scope.password
                data.oldPassword            = $scope.oldPassword
                data.confirmPassword    = $scope.confirmPassword
            }

            debugger // this is where I check the $scope only to find out it's not in sync

            patchUser( data )
        }

        $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 )
4

1 回答 1

0

谢谢@user2881430

事实上,使用ng-model="formData.data"和传递formDatang-submit函数是有效的。

这是代码:

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 = {} // empty form data to start with
        $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 => {
            // extend the form data with the data back from the server
            // this updates the form to display the 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 ) => {
            // extend form data here to add the csrf token required for form 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 )

我仍然很想知道为什么 $scope 不同步...

于 2016-03-17T20:29:31.557 回答