【发布时间】:2016-05-28 23:43:31
【问题描述】:
我正在构建一个 angularjs 应用程序,但我遇到了 $scope var 的问题。
我有以下定义:
$scope.data = {
object: {
id: undefined,
name: undefined,
category:
{
id: undefined,
name: undefined
},
description: undefined,
featured: 1,
seassons: undefined
},
progress: 0,
emptyResponse : false
};
问题是,当我尝试设置属性 $scope.data.object.name 时,我在控制台中收到以下错误:TypeError: Cannot set property 'name' of undefined。 有什么方法可以初始化 $scope var 中的数组吗?我试过了
$scope.data.object = []
这可行,但仅在该函数的范围内,而且如果我再次调用该函数,我将丢失以前的数据。 有没有办法做到这一点?另一种可行的方法是,如果我通过 ng-model 从视图中设置该属性的值,但在某些情况下,我需要在控制器中执行一些逻辑。
控制器定义正确
function VideoCreateController($scope,....)
完整的控制器,失败的方法是 IsValid,但如果我在未完成视图中的某些字段的情况下执行 Create 函数(当我尝试分配这些值时,我得到未定义)
(function() {
'use strict';
angular
.module('naut')
.controller('VideoCreateController', VideoCreateController);
function VideoCreateController($scope, $rootScope, $location, $state, SessionService, ProgramFactory, SeassonFactory, VideoFactory, CategoryFactory, SubcategoryFactory, $filter, ngTableParams, SweetAlert, $routeParams, $translate){
var vm = this;
$rootScope.baseurl = "#/app/Video/";
$scope.data = {
object: {
id: undefined,
name: undefined,
category:
{
id: undefined,
name: undefined
},
description: undefined,
featured: 1,
belongtoprogram: false,
isfeatured: false,
adv: false,
images: undefined,
preview: undefined,
categories: undefined,
subcategories: undefined,
programs: undefined,
episode: undefined,
seassons: undefined
},
progress: 0,
videosubmitted: false,
uploading: false,
errorMessage: undefined,
error: false,
emptyResponse : false
};
$scope.image = null;
$scope.imageFileName = '';
$scope.uploadme = {};
$scope.uploadme.src = '';
var obj = [];
$scope.data.object = obj;
$scope.GetInformation = function() {
$rootScope.$emit('LOAD');
CategoryFactory.GetAll()
.then(function(response){
ProgramFactory.GetAll()
.then(function(programresponse){
if (response.success && programresponse.success) {
$scope.data.object.categories = response.data;
$scope.data.object.subcategories = null;
$scope.data.object.programs = programresponse.data;
$scope.data.object.seassons = null;
console.log($scope.data.object);
}
else if(response.code == "ERROR__NOT_AUTHORIZED")
{
$location.path('/NotAuthorized');
}
else
{
$scope.data.error = true;
$scope.data.errorMessage = response.code;
}
$rootScope.$emit('UNLOAD');
}, function(response){
if (response == null) {
$scope.data.error = true;
$scope.data.errorMessage = "ERROR__SERVER_NON_WORKING";
}
else
{
$scope.data.error = true;
$scope.data.errorMessage = response.Message;
}
$rootScope.$emit('UNLOAD');
});
});
}
$scope.GetSubcategories = function(id) {
$rootScope.$emit('LOAD');
SubcategoryFactory.GetAll(id)
.then(function(response){
console.log(response);
if (response.success) {
$scope.data.object.subcategories = response.data;
console.log($scope.data.object);
}
else if(response.code == "ERROR__NOT_AUTHORIZED")
{
$location.path('/NotAuthorized');
}
else
{
$scope.data.error = true;
$scope.data.errorMessage = response.code;
}
$rootScope.$emit('UNLOAD');
}, function(response){
if (response == null) {
$scope.data.error = true;
$scope.data.errorMessage = "ERROR__SERVER_NON_WORKING";
}
else
{
$scope.data.error = true;
$scope.data.errorMessage = response.Message;
}
$rootScope.$emit('UNLOAD');
});
}
$scope.GetSeassons = function(id) {
$rootScope.$emit('LOAD');
SeassonFactory.GetAll(id)
.then(function(response){
console.log(response);
if (response.success) {
$scope.data.object.seassons = response.data;
}
else if(response.code == "ERROR__NOT_AUTHORIZED")
{
$location.path('/NotAuthorized');
}
else
{
$scope.data.error = true;
$scope.data.errorMessage = response.code;
}
$rootScope.$emit('UNLOAD');
}, function(response){
if (response == null) {
$scope.data.error = true;
$scope.data.errorMessage = "ERROR__SERVER_NON_WORKING";
}
else
{
$scope.data.error = true;
$scope.data.errorMessage = response.Message;
}
$rootScope.$emit('UNLOAD');
});
}
$scope.IsValid = function() {
var valid = true;
if(!$scope.data.object.name)
valid = false;
if(!$scope.data.object.description)
valid = false;
if(!$scope.data.object.subcategory)
valid = false;
if($scope.data.object.belongtoprogram && !$scope.data.object.episode && !$scope.data.object.seasson)
valid = false;
return valid;
}
$scope.Create = function(isValid) {
if (isValid) {
$rootScope.$emit('LOAD');
var params = {
id: $scope.data.object.id,
name: $scope.data.object.name,
preview: $scope.data.object.preview,
adv: $scope.data.object.adv,
featured: $scope.data.object.featured,
description: $scope.data.object.description,
episode: $scope.data.object.episode,
subcategory:
{
id: $scope.data.object.subcategory.id
},
seasson:
{
id: $scope.data.object.seasson !== undefined ? $scope.data.object.seasson.id : null
}
};
if(!$scope.data.object.isfeatured)
params.featured = 0;
VideoFactory.Create(params).then(function(response){
if (response.success) {
$state.go('app.video_index');
}
else
{
$scope.data.error = true;
$scope.data.errorMessage = response.code;
}
$rootScope.$emit('UNLOAD');
}, function(response){
if (response == null) {
$scope.data.error = true;
$scope.data.errorMessage = "ERROR__SERVER_NON_WORKING";
}
else
{
$scope.data.error = true;
$scope.data.errorMessage = response.code;
}
$rootScope.$emit('UNLOAD');
});
};
}
$scope.selected = function(image)
{
$scope.data.object.preview = image.source;
}
var callback = function(e){
$scope.$apply(function(){
$scope.data.progress = Math.round(e.loaded / e.total * 100);
});
};
$scope.reset = function()
{
$scope.data.object.id = undefined;
$scope.data.object.images = undefined;
$scope.data.object.source = undefined;
$scope.data.object.preview = undefined;
$scope.data.object.description = undefined;
$scope.data.videosubmitted = false;
$scope.data.object.name = undefined;
$scope.data.uploading = false;
};
$scope.upload = function(item) {
$scope.data.videosubmitted = true;
$scope.data.object.name = item.name.substr(0, item.name.lastIndexOf('.'));
$scope.data.uploading = true;
var params = {
files: item
};
VideoFactory.Save(params, callback).then(function(response){
response = JSON.parse(response);
$scope.data.uploading = false;
if (response.success) {
$scope.data.object.id = response.data.id;
$scope.data.object.images = response.data.images;
$scope.data.object.source = response.data.source;
$scope.data.object.preview = response.data.preview;
}
else
{
$scope.data.error = true;
$scope.data.errorMessage = response.code;
}
}, function(response){
if (response == null) {
$scope.data.error = true;
$scope.data.errorMessage = "ERROR__SERVER_NON_WORKING";
}
else
{
$scope.data.error = true;
$scope.data.errorMessage = response.code;
}
$scope.data.uploading = false;
});
}
$scope.GetInformation();
}
})();
查看:
<div ng-controller="VideoCreateController as controller" nv-file-drop="" uploader="uploader" filters="queueLimit, customFilter">
<a ng-href="{{baseurl}}Index" class="mr btn btn-labeled btn-default">
<span class="btn-label"><i class="fa fa-arrow-left"></i>
</span><span translate="PAGE.BACK" class="nopadding"></span></a>
<div class="app-view-header">
<span translate="PAGE.CREATE" class="nopadding"></span><small><span translate="MODULES.VIDEO.A-VIDEO" class="nopadding"></span></small>
</div>
<div class="row">
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading"><h1><span translate="MODULES.VIDEO.CREATE" class="nopadding"></span></h1></div>
<div class="panel-body">
<div class="row">
<div class="col-md-12">
<form role="form" name="data" class="mb-lg" ng-submit="Create(data.$valid)" novalidate>
<div class="row" ng-show="data.error">
<div class="col-md-12">
<div class="alert ng-isolate-scope alert-danger alert-dismissable" ng-class="['alert-' + (type || 'warning'), closeable ? 'alert-dismissable' : null]" role="alert" type="danger">
<div>
<span class="ng-binding ng-scope"><span translate="ERROR.{{data.errorMessage}}" class="nopadding"></span></span>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="row" ng-show="!data.videosubmitted">
<div class="col-md-10 no-padding-right">
<div class="dropzone" id="dropbox" callback-fn="upload(video)" file-dropzone="[video/mp4, video/3gpp, video/quicktime, video/x-msvideo, video/x-ms-wmv]"
file="image" file-name="imageFileName" data-max-file-size="3000">
<span translate="MODULES.VIDEO.DROPVIDEO"></span>
</div>
</div>
<div class="col-md-2 upload-btn no-padding-left">
<label class="upload-search btn btn-primary no-padding">
<div>
<input type="file" onchange="angular.element(this).scope().upload(this.files[0])"/>
<i class="fa fa-upload"></i>
<span translate="COMMON.FILESEARCH"></span>
</div>
</label>
</div>
</div>
<div class="video-data" ng-show="data.videosubmitted">
<div class="row">
<div class="col-md-8">
<div class="row margin-bottom-small">
<div class="col-md-6">
<div class="form-group">
<label for="name" class="col-sm-2 control-label" translate="COMMON.NAME"></label>
<div class="col-sm-10">
<input id="name" ng-model="data.object.name" type="text" required ng-class="{ 'has-error' : data.object.name.$invalid && !data.object.name.$pristine }" ng-minlength="2" class="form-control">
</div>
</div>
</div>
</div>
<div class="row margin-bottom-small">
<div class="col-md-6">
<div class="form-group">
<div class="row">
<div class="col-md-12">
<label for="name" class="col-sm-2 control-label" translate="MODULES.CATEGORY.CATEGORY"></label>
<div class="col-sm-10">
<ui-select ng-model="data.object.category" ng-change="GetSubcategories(data.object.category.id)" class="text-left">
<ui-select-match placeholder="Select a category...">{{data.object.category.name}}</ui-select-match>
<ui-select-choices repeat="item in data.object.categories">
<span ng-bind-html="item.name"></span>
</ui-select-choices>
</ui-select>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="name" class="col-sm-2 control-label" translate="MODULES.SUBCATEGORY.SUBCATEGORY"></label>
<div class="col-sm-10">
<ui-select ng-model="data.object.subcategory" class="text-left">
<ui-select-match placeholder="Select a category...">{{data.object.subcategory.name}}</ui-select-match>
<ui-select-choices repeat="item in data.object.subcategories">
<span ng-bind-html="item.name"></span>
</ui-select-choices>
</ui-select>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="checkbox c-checkbox pull-left mt0">
<label class="col-md-12">
<input type="checkbox" ng-model="data.object.belongtoprogram" id="belongtoprogram" value="" />
<span class="fa fa-check checkbox-margin"></span><label for="belongtoprogram" class="nopadding" translate="MODULES.VIDEO.INPROGRAM"></label>
</label>
</div>
</div>
</div>
<div class="row margin-bottom-small" ng-show="data.object.belongtoprogram">
<div class="col-md-4">
<div class="form-group">
<div class="row">
<div class="col-md-12">
<label for="name" class="col-sm-2 control-label" translate="MODULES.PROGRAM.PROGRAM"></label>
<div class="col-sm-10">
<ui-select ng-model="data.object.program" ng-change="GetSeassons(data.object.program.id)" class="text-left">
<ui-select-match placeholder="Select a program...">{{data.object.program.name}}</ui-select-match>
<ui-select-choices repeat="item in data.object.programs">
<span ng-bind-html="item.name"></span>
</ui-select-choices>
</ui-select>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label for="name" class="col-sm-2 control-label" translate="MODULES.SEASSON.SEASSON"></label>
<div class="col-sm-10">
<ui-select ng-model="data.object.seasson" class="text-left">
<ui-select-match placeholder="Select a seasson...">{{data.object.seasson.name}}</ui-select-match>
<ui-select-choices repeat="item in data.object.seassons">
<span ng-bind-html="item.name"></span>
</ui-select-choices>
</ui-select>
</div>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label for="name" class="col-sm-2 control-label" translate="MODULES.VIDEO.EPISODE"></label>
<div class="col-sm-4">
<input ng-model="data.object.episode" type="number" ng-class="{ 'has-error' : data.object.episode.$invalid && !data.object.episode.$pristine }" ng-minlength="1" ng-maxlength="3" class="form-control">
</div>
</div>
</div>
</div>
<div class="row margin-bottom-small">
<div class="col-md-12">
<div class="form-group">
<label for="name" class="col-sm-12 control-label" translate="MODULES.VIDEO.DESCRIPTION"></label>
<div class="col-sm-12">
<div text-angular="" ng-model="data.object.description" name="data.object.description" class="btn-group-small"></div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="checkbox c-checkbox pull-left mt0">
<label class="col-md-12">
<input type="checkbox" ng-model="data.object.adv" id="adv" value="" />
<span class="fa fa-check checkbox-margin"></span><label for="adv" class="nopadding" translate="MODULES.VIDEO.ADVERTISEMENT"></label>
</label>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="checkbox c-checkbox pull-left mt0">
<label class="col-md-12">
<input type="checkbox" ng-model="data.object.isfeatured" id="isfeatured" value="" />
<span class="fa fa-check checkbox-margin"></span><label for="isfeatured" class="nopadding" translate="MODULES.VIDEO.FEATURED"></label>
</label>
</div>
</div>
</div>
<div class="row margin-bottom-small" ng-show="data.object.isfeatured">
<div class="col-md-6">
<div class="form-group">
<label for="name" class="col-sm-2 control-label" translate="MODULES.VIDEO.ORDER"></label>
<div class="col-sm-4">
<input ng-model="data.object.featured" type="number" ng-class="{ 'has-error' : data.object.featured.$invalid && !data.object.featured.$pristine }" ng-minlength="1" ng-maxlength="2" class="form-control">
</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="row">
<div class="col-md-12">
<div ng-show="data.uploading">
<progressbar value="data.progress" class="progress-striped active">{{data.progress}}%</progressbar>
</div>
</div>
</div>
<div class="row" ng-show="data.object.preview">
<div class="col-md-12">
<img class="img-responsive center" src="/app/videos/{{data.object.source}}/screenshots/{{data.object.preview}}">
</div>
<div class="col-md-12">
<div ng-show="data.object.images != null">
<h5 class="page-header"><span translate="MODULES.VIDEO.SELECT-PREVIEW"></span></h5>
<div ng-repeat="image in data.object.images" class="col-lg-3">
<img class="img-thumbnail" ng-class="{ 'preview-selected': image.source == data.object.preview, 'preview-not-selected': image.source != data.object.preview }" ng-click="selected(image)" src="/app/videos/{{data.object.source}}/screenshots/{{image.source}}">
</div>
</div>
</div>
</div>
</div>
</div>
<hr />
<div class="row">
<div class="col-md-12 text-right">
<button type="reset" class="btn btn-labeled btn-danger" ng-click="reset()">
<span class="btn-label"><i class="fa fa-times"></i>
</span><span translate="PAGE.RESET" class="nopadding"></span>
</button>
<button ng-disabled="data.$invalid && !IsValid()" type="submit" class="btn btn-labeled btn-success">
<span class="btn-label"><i class="fa fa-check"></i>
</span><span translate="PAGE.CREATE" class="nopadding"></span>
</button>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
【问题讨论】:
-
如果您向控制器展示导致问题的相关代码,这将有所帮助。
-
见minimal reproducible example。没有足够的证据让我们重现或正确分析问题。显示所有相关代码
-
嗨,@JimCote 和 charlietfl 我刚刚添加了控制器和视图。如果您看到任何奇怪的东西,请告诉我。这是我的第一个 angularjs 应用程序,所以除了我的问题之外,也许你有一些最佳实践可以与我分享,我没有在这里关注。
-
您在控制器中设置
$scope.data.object = {...},然后将其更改为$scope.data.object = []。 -
请只显示与实际问题相关的代码。我们不需要涉足不相关的代码。你从一个极端的代码不足变成了另一个极端
标签: javascript angularjs scope angularjs-scope