控制器函数中的参数返回undefined ReferenceError

时间:2015-08-20 01:09:09

标签: asp.net-mvc angularjs

我正在通过this AngularJS的学习实验室。我可以让这个例子按原样工作(修复一个小错误)。

我还试图通过引用this guide来学习一些关于AngluarJS的良好编码实践。这导致了一个如下所示的js文件:

(function () {
'use strict';

angular.module('QuizApp', []);

angular.module('QuizApp').controller('QuizCtrl', QuizController);

function QuizController($http) {
    var vm = this;

    vm.answer = answer();
    vm.answered = false;
    vm.correctAnswer = false;
    vm.nextQuestion = nextQuestion();
    vm.options = [];
    vm.sendAnswer = sendAnswer(option);
    vm.title = "loading question...";
    vm.working = false;

    function answer() {
        return vm.correctAnswer ? 'correct' : 'incorrect';
    }

    function nextQuestion() {
        vm.working = true;
        vm.answered = false;
        vm.title = "loading question...";
        vm.options = [];

        $http.get("/api/trivia")
        .success(function (data, status, headers, config) {
            vm.options = data.options;
            vm.title = data.title;
            vm.answered = false;
            vm.working = false;
        }).error(function (data, status, headers, config) {
            vm.title = "Oops... something went wrong.";
            vm.working = false;
        });
    }

    function sendAnswer(option) {
        vm.working = true;
        vm.answered = true;

        $http.post('/api/trivia', { 'questionId': option.questionId, 'optionId': option.id })
        .success(function (data, status, headers, config) {
            vm.correctAnswer = (data === true);
            vm.working = false;
        })
        .error(function (data, status, headers, config) {
            vm.title = "Oops... something went wrong.";
            vm.working = false;
        });
    }
};
})();

但是,此代码在页面加载时抛出以下错误。

  

ReferenceError:'option'未定义      在QuizController(http://localhost:17640/Scripts/app/quiz-controller.js:16:9)      在调用(http://localhost:17640/Scripts/angular.js:4473:7)      在匿名函数(http://localhost:17640/Scripts/angular.js:9093:11)      at nodeLinkFn(http://localhost:17640/Scripts/angular.js:8205:13)      在compositeLinkFn(http://localhost:17640/Scripts/angular.js:7637:13)      在compositeLinkFn(http://localhost:17640/Scripts/angular.js:7641:13)      在compositeLinkFn(http://localhost:17640/Scripts/angular.js:7641:13)      在compositeLinkFn(http://localhost:17640/Scripts/angular.js:7641:13)      在compositeLinkFn(http://localhost:17640/Scripts/angular.js:7641:13)      在publicLinkFn(http://localhost:17640/Scripts/angular.js:7512:30

无论出于何种原因,它似乎都在尝试立即执行sendAnswer。由于它失败了,javascript会在页面中间停止显示角度属性名称{{title}},而不是在页面上呈现问题。我尝试了不同的方法来定义和调用vm.sendAnswerfunction sendAnswer,但没有运气。

供参考,这是我视图的代码(注意ng-repeat on options - 这个视图代码在完全遵循实验练习时非常有效):

<div id="bodyContainer" ng-app="QuizApp">
<section id="content">
    <div class="container">
        <div class="row">
            <div class="flip-container text-center col-md-12" ng-controller="QuizCtrl" ng-init="nextQuestion()">
                <div class="back" ng-class="{flip: answered, correct: correctAnswer, incorrect:!correctAnswer}">
                    <p class="lead">{{answer()}}</p>
                    <p>
                        <button class="btn btn-info btn-lg next option" ng-click="nextQuestion()" ng-disabled="working">Next Question</button>
                    </p>
                </div>
                <div class="front" ng-class="{flip: answered}">
                    <p class="lead">{{title}}</p>
                    <div class="row text-center">
                        <button class="btn btn-info btn-lg option" ng-repeat="option in options" ng-click="sendAnswer(option)" ng-disabled="working">{{option.title}}</button>
                    </div>
                </div>
            </div>
        </div>
    </div>
</section>
</div>

如何保留我的编码实践(基本上,避免在这种情况下使用$scope并在控制器顶部声明我的所有viewmodel属性)但是还能使函数正常运行?

2 个答案:

答案 0 :(得分:0)

你打算送进去吗? vm.options = []; vm.sendAnswer = sendAnswer(option);

vm.options进入sendAnswer()函数,因为未定义option。如果将'option'括在一个字符串中并将其传递给函数,你将不会收到错误。但是你不会得到你想要的对象。 将其添加到顶部var option = {}

答案 1 :(得分:0)

我现在有这个例子。

首先,插入函数的控制器属性只需要引用函数的名称。

vm.answer = answer;
vm.nextQuestion = nextQuestion;
vm.sendAnswer = sendAnswer;

然后我们在视图中需要控制器的别名,以便我们可以更容易地引用它。

<div class="flip-container text-center col-md-12" ng-controller="QuizCtrl as quiz" ng-init="quiz.nextQuestion()">
    <div class="back" ng-class="{flip: quiz.answered, correct: quiz.correctAnswer, incorrect:!quiz.correctAnswer}">
        <p class="lead">{{quiz.answer()}}</p>
        <p>
            <button class="btn btn-info btn-lg next option" ng-click="quiz.nextQuestion()" ng-disabled="quiz.working">Next Question</button>
        </p>
    </div>
    <div class="front" ng-class="{flip: quiz.answered}">
        <p class="lead">{{quiz.title}}</p>
        <div class="row text-center">
            <button class="btn btn-info btn-lg option" ng-repeat="option in quiz.options" ng-click="quiz.sendAnswer(option)" ng-disabled="quiz.working">{{option.title}}</button>
        </div>
    </div>
</div>

这就是它。只需清理角度控制器中的属性定义,然后在视图上使用控制器的别名。其他所有内容都与问题中的内容完全相同。

现在是完整的代码。角度控制器:

(function () {
'use strict';

angular.module('QuizApp', []);

angular.module('QuizApp').controller('QuizCtrl', QuizController);

function QuizController($http) {
    var vm = this;

    vm.answer = answer;
    vm.answered = false;
    vm.correctAnswer = false;
    vm.nextQuestion = nextQuestion;
    vm.options = [];
    vm.sendAnswer = sendAnswer;
    vm.title = "loading question...";
    vm.working = false;

    function answer() {
        return vm.correctAnswer ? 'correct' : 'incorrect';
    };

    function nextQuestion() {
        vm.working = true;
        vm.answered = false;
        vm.title = "loading question...";
        vm.options = [];

        $http.get("/api/trivia")
        .success(function (data, status, headers, config) {

            var answerOptions = data.options;

            while (answerOptions.length > 0){
                var random = Math.floor(Math.random() * answerOptions.length, 0);
                alert(random);

                vm.options.push(answerOptions[random]);
                answerOptions.splice(random, 1);
            }

            //vm.options = data.options;
            vm.title = data.title;
            vm.answered = false;
            vm.working = false;
        }).error(function (data, status, headers, config) {
            vm.title = "Oops... something went wrong.";
            vm.working = false;
        });
    };

    function sendAnswer(option)
    {
        vm.working = true;
        vm.answered = true;

        $http.post('/api/trivia', { 'questionId': option.questionId, 'optionId': option.id }).success(function (data, status, headers, config) {
            vm.correctAnswer = (data === true);
        }).error(function (data, status, headers, config) {
            vm.title = "Oops... something went wrong";                
        });

        vm.working = false;
    }
};
})();

MVC索引视图:

@{
    ViewBag.Title = "Play";
}

<div id="bodyContainer" ng-app="QuizApp">
    <section id="content">
        <div class="container">
            <div class="row">
                <div class="flip-container text-center col-md-12" ng-controller="QuizCtrl as quiz" ng-init="quiz.nextQuestion()">
                    <div class="back" ng-class="{flip: quiz.answered, correct: quiz.correctAnswer, incorrect:!quiz.correctAnswer}">
                        <p class="lead">{{quiz.answer()}}</p>
                        <p>
                            <button class="btn btn-info btn-lg next option" ng-click="quiz.nextQuestion()" ng-disabled="quiz.working">Next Question</button>
                        </p>
                    </div>
                    <div class="front" ng-class="{flip: quiz.answered}">
                        <p class="lead">{{quiz.title}}</p>
                        <div class="row text-center">
                            <button class="btn btn-info btn-lg option" ng-repeat="option in quiz.options" ng-click="quiz.sendAnswer(option)" ng-disabled="quiz.working">{{option.title}}</button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>
</div>

@section scripts {
    @Scripts.Render("~/Scripts/angular.js")
    @Scripts.Render("~/Scripts/app/quiz-controller.js")
}