userServic won't pass data to back-end: Cannot

2019-08-07 16:52发布

问题:

I have a Change Password feature on my User Control Panel that is not working. It pick's up values from input and passes them from controller to service, service receives them but when he treys to hit back-end with them the debug console returns: Cannot read property 'protocol' of undefined.

Important: Please refer to my previews question here before you write your solution to understand why I have to use fields of an object to scope input. Pleas consider that sending whole object to backend is not an option, thank you.

Form (.html):

<accordion-group heading="Change password" is-open="changePasswordStatus.open" style="cursor: pointer">
    <div>
        <div>
            <form class="form-horizontal" role="form">
                <form-row model="password.newPassword" name="New: " size="col-sm-8"></form-row>
                <form-row model="password.repeatedNewPassword" name="Repeat: " size="col-sm-8"></form-row>
                <form-row model="password.currentPassword" name="Current: " size="col-sm-8"></form-row>
                <br>
            </form>
        </div>
        <div>
            <button class="btn btn-default btn-sm" data-ng-click="changePassword()">Save</button>
            <button class="btn btn-warning btn-sm" ng-click="changePasswordStatus.open = !changePasswordStatus.open">Cancel</button>
        </div>
    </div>
</accordion-group>

userController.js:

collectionsApp.controller('userController', function($scope, userService, $timeout, $state) {
    $scope.password = {
        newPassword : "",
        repeatedNewPassword : "",
        currentPassword : ""
    }

    $scope.init = function() {
        userService.getCurrentUser(getCurrentUser);
    }

    $scope.changePassword = function() {
        if ($scope.password.newPassword === $scope.password.repeatedNewPassword) {
            userService.changePassword($scope.password.newPassword, $scope.password.currentPassword);
    }
}

...

userService.js:

collectionsApp.service('userService', function($http) {
    return {
        changePassword : function(newPassword, currentPassword) {
            $http.post('/user/changePassword', newPassword, currentPassword);
        }

    };
});

Debug:

Error in console:

回答1:

According to the $http reference, the post method arguments are

  1. url
  2. data object
  3. option object

So, try this :

collectionsApp.service('userService', function($http) {
    return {
        changePassword : function(newPassword, currentPassword) {
            var data = {
                newPassword: newPassword,
                currentPassword: currentPassword
            };
            $http.post('/user/changePassword', data);
        }

    };
});


回答2:

I have managed to solve this problem. There were three solutions. In back-end I have Java controller that was configured to accept @RequestBody with POST method. First it was configured for two strings but as it happens Angular's $http post is is meant to receive three parms - 1. url, 2.data, 3. config object (as @RémiB. pointed out). So logical solution was to send object, and to receive it as an generic object like Object data but this object has no getters and setters so it was not possible to extract data. Absolutely Not acceptable solution was to create utility class with getters and setters designed for this kind of data. Less not acceptable solution was to add new filed (newPassword to existing class User) so data received with this class could be processed. Third - dubious solution was to receive data as generic Object object and do a toString() ond this object and write a code for extracting substrings from string. This sounded really wrong and I did not wanted to do that. Last solution was least unacceptable: to change methods to GET and send data in url (from Angular service) and reactive it as string via @PathVariables in Java backend. So, long story short:

changePassword : function(newPassword, currentPassword) {
    $http.get('/user/changePassword/'+newPassword+'/'+currentPassword);
}

And in back-end:

@RequestMapping(value = "/changePassword/{newPassword}/{currentPassword}", method = RequestMethod.GET)
    public HashMap<String, String> changePassword(@PathVariable("newPassword") String newPassword, @PathVariable("currentPassword") String currentPassword) {  
....
}