angularjsangularjs-controllerangularjs-validation

AngularJs and Controller alias


I tried to alias the AngularJS controller in the view, but for some strange reason - it does not seem to respond when I prefix the methods and properties - any idea what might be causing it?

Here's my view (I'm using it with Laravel 5.1):

@extends('admin.template.layout-login')

@section('content')

    <div class="row">

        <div class="large-6 medium-8 columns large-offset-3 medium-offset-2" ng-controller="LoginController as login">

            <form
                name="htmlForm"
                class="panel hide"
                ng-submit="login.submit()"
                ng-class="{ 'show-block' : !login.isRequestCompleted() }"
                novalidate
                >

                <label for="username">
                    Username: *
                    <ng-messages
                            for="htmlForm.username.$error"
                            class="hide"
                            ng-class="{ 'show-inline' : login.isSubmitted() }"
                            >
                        <ng-message
                                when="required"
                                class="warning"
                                >Please provide your email address</ng-message>
                        <ng-message
                                when="email"
                                class="warning"
                                >Invalid email address</ng-message>
                        <ng-message
                                when="unsuccessful"
                                class="warning"
                                >Incorrect login details</ng-message>
                        <ng-message
                                when="suspended"
                                class="warning"
                                >Your account has been suspended</ng-message>
                    </ng-messages>
                </label>

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

                <label for="password">
                    Password: *
                    <ng-messages
                            for="htmlForm.password.$error"
                            class="hide"
                            ng-class="{ 'show-inline' : login.isSubmitted() }"
                            >
                        <ng-message
                                when="required"
                                class="warning"
                                >Please provide your password</ng-message>
                        <ng-message
                                when="password"
                                class="warning"
                                >Invalid password</ng-message>
                    </ng-messages>
                </label>

                <input
                    type="password"
                    ng-model="formData.password"
                    name="password"
                    id="password"
                    required
                    password
                    >

                <label for="remember">
                    <input
                        type="checkbox"
                        ng-model="formData.remember"
                        name="remember"
                        id="remember"
                        > Remember Me
                </label>

                <input
                        type="submit"
                        class="small button"
                        value="SEND ENQUIRY"

                        ng-if="!login.isOutForDelivery()"
                        >
                <button
                        type="button"
                        class="small button"
                        disabled
                        ng-if="login.isOutForDelivery()"
                        >
                    PLEASE WAIT <i class="fa fa-spinner fa-spin"></i>
                </button>

            </form>


            <div
                class="hide"
                ng-class="{ 'show-block' : login.isRequestCompleted() }"
                ng-bind-html="login.trustAsHtml(confirmation)"
                ></div>


        </div>

    </div>

@endsection

and here's the AngularJS controller module:

(function(window, angular, app) {

    "use strict";

    app.controller(
        'LoginController',
        [
            '$scope',
            '$controller',
            '$window',
            function(
                $scope,
                $controller,
                $window
            ) {

                angular.extend(this, $controller('FormController', { $scope: $scope }));

                $scope.submit = function() {

                    if ( ! $scope.isValid()) return false;

                    $scope.data = {
                        username : $scope.formData.username,
                        password : $scope.formData.password
                    };

                    $scope.submitRequest(
                            '/admin',
                            $scope.data
                        )
                        .success(function(data, status, headers, config, statusText) {

                            $window.location.href = data.url;

                        })
                        .error(function(data, status, headers, config, statusText) {

                            $scope.validation(data);
                            $scope.endOutForDelivery();
                            return false;

                        });

                };

            }
        ]
    );

})(window, window.angular, window.CmdSystem.App);

Plus the FormController that the previous extends:

(function(window, angular, app) {

    "use strict";

    app.controller(
        'FormController',
        [
            '$scope',
            'RequestService',
            'ContentService',
            function(
                $scope,
                RequestService,
                ContentService
            ) {

                $scope.outForDelivery = false;
                $scope.requestCompleted = false;

                $scope.submitRequest = function(url, formData) {

                    $scope.outForDelivery = true;

                    return RequestService.post(url, formData);

                };

                $scope.responseReceived = function() {

                    $scope.requestCompleted = true;
                    $scope.outForDelivery = false;

                };

                $scope.isResponseReceived = function() {

                    return $scope.requestCompleted && ! $scope.outForDelivery;

                };

                $scope.endOutForDelivery = function() {

                    $scope.outForDelivery = false;

                };

                $scope.trustAsHtml = ContentService.trustAsHtml;

                $scope.isValid = function() {

                    return $scope.htmlForm.$valid;

                };

                $scope.isSubmitted = function() {

                    return  $scope.htmlForm.$submitted &&
                            ! $scope.isRequestCompleted();

                };

                $scope.isRequestCompleted = function() {

                    return $scope.requestCompleted;

                };

                $scope.isOutForDelivery = function() {

                    return $scope.outForDelivery;

                };

                $scope.validation = function(data) {

                    angular.forEach(data, function(value, key) {

                        this[key].$error[value] = true;

                    }, $scope.htmlForm);

                };

            }
        ]
    );

})(window, window.angular, window.CmdSystem.App);

Solution

  • None of the methods are on the controller. They're all defined on the $scope. So you can't access them using the login alias, which refers to the controller, not to the scope.

    If you want to be able to call

    login.foo()
    

    from the view, then the method must be set on the controller, not on the scope:

    this.foo = function() { ... };