2015-05-29 54 views
0

AngularJS模塊的定義中,[]是該模塊上其他依賴模塊的參數。AngularJS模塊定義中的參數[]是強制性的嗎?

<script> 
var app = angular.module('myApp',[]); 
app.controller("myCtrl", function($scope) { 
    $scope.firstName = "John"; 
    $scope.lastName = "Doe"; 
}); 
</script> 

我的問題是,
是該參數[]必要,因爲下面的鏈接或例如他們沒有提到[]參數,但在上面的例子中(w3schooles),如果我們去掉「 []'參數,那麼代碼將不會給出正確的輸出see it

請參閱此鏈接openstack,他們沒有使用[]參數

var module = angular.module('hz.dashboard.launch-instance'); 
/** 
* @ngdoc service 
* @name launchInstanceModel 
* 
* @description 
* This is the M part in MVC design pattern for launch instance 
* wizard workflow. It is responsible for providing data to the 
* view of each step in launch instance workflow and collecting 
* user's input from view for creation of new instance. It is 
* also the center point of communication between launch instance 
* UI and services API. 
*/ 
module.factory('launchInstanceModel', ['$q', 
'cinderAPI', 
'glanceAPI', 
'keystoneAPI', 
'neutronAPI', 
'novaAPI', 
'novaExtensions', 
'securityGroup', 
'serviceCatalog', 
function ($q, 
cinderAPI, 
glanceAPI, 
keystoneAPI, 
neutronAPI, 
novaAPI, 
novaExtensions, 
securityGroup, 
serviceCatalog) { 
var initPromise, 
allNamespacesPromise; 
// Constants (const in ES6) 
var NON_BOOTABLE_IMAGE_TYPES = ['aki', 'ari'], 
SOURCE_TYPE_IMAGE = 'image', 
SOURCE_TYPE_SNAPSHOT = 'snapshot', 
SOURCE_TYPE_VOLUME = 'volume', 
SOURCE_TYPE_VOLUME_SNAPSHOT = 'volume_snapshot'; 
/** 
* @ngdoc model api object 
*/ 
var model = { 
initializing: false, 
initialized: false, 
/** 
* @name newInstanceSpec 
* 
* @description 
* A dictionary like object containing specification collected from user's 
* input. Its required properties include: 
* 
* @property {String} name: The new server name. 
* @property {String} source_type: The type of source 
* Valid options: (image | snapshot | volume | volume_snapshot) 
* @property {String} source_id: The ID of the image/volume to use. 
* @property {String} flavor_id: The ID of the flavor to use. 
* 
* Other parameters are accepted as per the underlying novaclient: 
* - https://github.com/openstack/python-novaclient/blob/master/novaclient/v2/servers.py#L417 
* But may be required additional values as per nova: 
* - https://github.com/openstack/horizon/blob/master/openstack_dashboard/api/rest/nova.py#L127 
* 
* The JS code only needs to set the values below as they are made. 
* The createInstance function will map them appropriately. 
*/ 
// see initializeNewInstanceSpec 
newInstanceSpec: {}, 
/** 
* cloud service properties, they should be READ-ONLY to all UI controllers 
*/ 
availabilityZones: [], 
flavors: [], 
allowedBootSources: [], 
images: [], 
allowCreateVolumeFromImage: false, 
arePortProfilesSupported: false, 
imageSnapshots: [], 
keypairs: [], 
metadataDefs: { 
flavor: null, 
image: null, 
volume: null 
}, 
networks: [], 
neutronEnabled: false, 
novaLimits: {}, 
profiles: [], 
securityGroups: [], 
volumeBootable: false, 
volumes: [], 
volumeSnapshots: [], 
/** 
* api methods for UI controllers 
*/ 
initialize: initialize, 
createInstance: createInstance 
}; 
// Local function. 
function initializeNewInstanceSpec(){ 
model.newInstanceSpec = { 
availability_zone: null, 
admin_pass: null, 
config_drive: false, 
user_data: '', // REQUIRED Server Key. Null allowed. 
disk_config: 'AUTO', 
flavor: null, // REQUIRED 
instance_count: 1, 
key_pair: [], // REQUIRED Server Key 
name: null, // REQUIRED 
networks: [], 
profile: {}, 
security_groups: [], // REQUIRED Server Key. May be empty. 
source_type: null, // REQUIRED for JS logic (image | snapshot | volume | volume_snapshot) 
source: [], 
vol_create: false, // REQUIRED for JS logic 
vol_device_name: 'vda', // May be null 
vol_delete_on_terminate: false, 
vol_size: 1 
}; 
} 
/** 
* @ngdoc method 
* @name launchInstanceModel.initialize 
* @returns {promise} 
* 
* @description 
* Send request to get all data to initialize the model. 
*/ 
function initialize(deep) { 
var deferred, promise; 
// Each time opening launch instance wizard, we need to do this, or 
// we can call the whole methods `reset` instead of `initialize`. 
initializeNewInstanceSpec(); 
if (model.initializing) { 
promise = initPromise; 
} else if (model.initialized && !deep) { 
deferred = $q.defer(); 
promise = deferred.promise; 
deferred.resolve(); 
} else { 
model.initializing = true; 
model.allowedBootSources.length = 0; 
promise = $q.all([ 
getImages(), 
novaAPI.getAvailabilityZones().then(onGetAvailabilityZones, noop), 
novaAPI.getFlavors(true, true).then(onGetFlavors, noop), 
novaAPI.getKeypairs().then(onGetKeypairs, noop), 
novaAPI.getLimits().then(onGetNovaLimits, noop), 
securityGroup.query().then(onGetSecurityGroups, noop), 
serviceCatalog.ifTypeEnabled('network').then(getNetworks, noop), 
serviceCatalog.ifTypeEnabled('volume').then(getVolumes, noop) 
]); 
promise.then(
function() { 
model.initializing = false; 
model.initialized = true; 
// This provides supplemental data non-critical to launching 
// an instance. Therefore we load it only if the critical data 
// all loads successfully. 
getMetadataDefinitions(); 
}, 
function() { 
model.initializing = false; 
model.initialized = false; 
} 
); 
} 
return promise; 
} 
/** 
* @ngdoc method 
* @name launchInstanceModel.createInstance 
* @returns {promise} 
* 
* @description 
* Send request for creating server. 
*/ 
function createInstance() { 
var finalSpec = angular.copy(model.newInstanceSpec); 
cleanNullProperties(); 
setFinalSpecBootsource(finalSpec); 
setFinalSpecFlavor(finalSpec); 
setFinalSpecNetworks(finalSpec); 
setFinalSpecKeyPairs(finalSpec); 
setFinalSpecSecurityGroups(finalSpec); 
return novaAPI.createServer(finalSpec); 
} 
function cleanNullProperties(finalSpec){ 
// Initially clean fields that don't have any value. 
for (var key in finalSpec) { 
if (finalSpec.hasOwnProperty(key) && finalSpec[key] === null) { 
delete finalSpec[key]; 
} 
} 
} 
// 
// Local 
// 
function onGetAvailabilityZones(data) { 
model.availabilityZones.length = 0; 
push.apply(model.availabilityZones, data.data.items 
.filter(function (zone) { 
return zone.zoneState && zone.zoneState.available; 
}) 
.map(function (zone) { 
return zone.zoneName; 
}) 
); 
if(model.availabilityZones.length > 0) { 
model.newInstanceSpec.availability_zone = model.availabilityZones[0]; 
} 
} 
// Flavors 
function onGetFlavors(data) { 
model.flavors.length = 0; 
push.apply(model.flavors, data.data.items); 
} 
function setFinalSpecFlavor(finalSpec) { 
if (finalSpec.flavor) { 
finalSpec.flavor_id = finalSpec.flavor.id; 
} else { 
delete finalSpec.flavor_id; 
} 
delete finalSpec.flavor; 
} 
// Keypairs 
function onGetKeypairs(data) { 
angular.extend(
model.keypairs, 
data.data.items.map(function (e) { 
e.keypair.id = e.keypair.name; 
return e.keypair; 
})); 
} 
function setFinalSpecKeyPairs(finalSpec) { 
// Nova only wants the key name. It is a required field, even if None. 
if(!finalSpec.key_name && finalSpec.key_pair.length === 1){ 
finalSpec.key_name = finalSpec.key_pair[0].name; 
} else if (!finalSpec.key_name) { 
finalSpec.key_name = null; 
} 
delete finalSpec.key_pair; 
} 
// Security Groups 
function onGetSecurityGroups(data) { 
model.securityGroups.length = 0; 
push.apply(model.securityGroups, data.data.items); 
// set initial default 
if (model.newInstanceSpec.security_groups.length === 0 && 
model.securityGroups.length > 0) { 
model.securityGroups.forEach(function (securityGroup) { 
if (securityGroup.name === 'default') { 
model.newInstanceSpec.security_groups.push(securityGroup); 
} 
}); 
} 
} 
function setFinalSpecSecurityGroups(finalSpec) { 
// pull out the ids from the security groups objects 
var security_group_ids = []; 
finalSpec.security_groups.forEach(function(securityGroup){ 
if(model.neutronEnabled) { 
security_group_ids.push(securityGroup.id); 
} else { 
security_group_ids.push(securityGroup.name); 
} 
}); 
finalSpec.security_groups = security_group_ids; 
} 
// Networks 
function getNetworks() { 
return neutronAPI.getNetworks().then(onGetNetworks, noop); 
} 
function onGetNetworks(data) { 
model.neutronEnabled = true; 
model.networks.length = 0; 
push.apply(model.networks, data.data.items); 
} 
function setFinalSpecNetworks(finalSpec) { 
finalSpec.nics = []; 
finalSpec.networks.forEach(function (network) { 
finalSpec.nics.push(
{ 
"net-id": network.id, 
"v4-fixed-ip": "" 
}); 
}); 
delete finalSpec.networks; 
} 
// Boot Source 
function getImages(){ 
return glanceAPI.getImages({status:'active'}).then(onGetImages); 
} 
function isBootableImageType(image){ 
// This is a blacklist of images that can not be booted. 
// If the image container type is in the blacklist 
// The evaluation will result in a 0 or greater index. 
return NON_BOOTABLE_IMAGE_TYPES.indexOf(image.container_format) < 0; 
} 
function onGetImages(data) { 
model.images.length = 0; 
push.apply(model.images, data.data.items.filter(function (image) { 
return isBootableImageType(image) && 
(!image.properties || image.properties.image_type !== 'snapshot'); 
})); 
addAllowedBootSource(model.images, SOURCE_TYPE_IMAGE, gettext('Image')); 
model.imageSnapshots.length = 0; 
push.apply(model.imageSnapshots,data.data.items.filter(function (image) { 
return isBootableImageType(image) && 
(image.properties && image.properties.image_type === 'snapshot'); 
})); 
addAllowedBootSource(model.imageSnapshots, SOURCE_TYPE_SNAPSHOT, gettext('Instance Snapshot')); 
} 
function getVolumes(){ 
var volumePromises = []; 
// Need to check if Volume service is enabled before getting volumes 
model.volumeBootable = true; 
addAllowedBootSource(model.volumes, SOURCE_TYPE_VOLUME, gettext('Volume')); 
addAllowedBootSource(model.volumeSnapshots, SOURCE_TYPE_VOLUME_SNAPSHOT, gettext('Volume Snapshot')); 
volumePromises.push(cinderAPI.getVolumes({ status: 'available', bootable: 1 }).then(onGetVolumes)); 
volumePromises.push(cinderAPI.getVolumeSnapshots({ status: 'available' }).then(onGetVolumeSnapshots)); 
// Can only boot image to volume if the Nova extension is enabled. 
novaExtensions.ifNameEnabled('BlockDeviceMappingV2Boot') 
.then(function(){ model.allowCreateVolumeFromImage = true; }); 
return $q.all(volumePromises); 
} 
function onGetVolumes(data) { 
model.volumes.length = 0; 
push.apply(model.volumes, data.data.items); 
} 
function onGetVolumeSnapshots(data) { 
model.volumeSnapshots.length = 0; 
push.apply(model.volumeSnapshots, data.data.items); 
} 
function addAllowedBootSource(rawTypes, type, label) { 
if (rawTypes && rawTypes.length > 0) { 
model.allowedBootSources.push({ 
type: type, 
label: label 
}); 
} 
} 
function setFinalSpecBootsource(finalSpec) { 
finalSpec.source_id = finalSpec.source && finalSpec.source[0] && finalSpec.source[0].id; 
delete finalSpec.source; 
switch (finalSpec.source_type.type) { 
case SOURCE_TYPE_IMAGE: 
setFinalSpecBootImageToVolume(finalSpec); 
break; 
case SOURCE_TYPE_SNAPSHOT: 
break; 
case SOURCE_TYPE_VOLUME: 
setFinalSpecBootFromVolumeDevice(finalSpec, 'vol'); 
break; 
case SOURCE_TYPE_VOLUME_SNAPSHOT: 
setFinalSpecBootFromVolumeDevice(finalSpec, 'snap'); 
break; 
default: 
// error condition 
console.log("Unknown source type: " + finalSpec.source_type); 
} 
// The following are all fields gathered into simple fields by 
// steps so that the view can simply bind to simple model attributes 
// that are then transformed a single time to Nova's expectation 
// at launch time. 
delete finalSpec.source_type; 
delete finalSpec.vol_create; 
delete finalSpec.vol_device_name; 
delete finalSpec.vol_delete_on_terminate; 
delete finalSpec.vol_size; 
} 
function setFinalSpecBootImageToVolume(finalSpec){ 
if(finalSpec.vol_create) { 
// Specify null to get Autoselection (not empty string) 
var device_name = finalSpec.vol_device_name ? finalSpec.vol_device_name : null; 
finalSpec.block_device_mapping_v2 = []; 
finalSpec.block_device_mapping_v2.push(
{ 
'device_name': device_name, 
'source_type': SOURCE_TYPE_IMAGE, 
'destination_type': SOURCE_TYPE_VOLUME, 
'delete_on_termination': finalSpec.vol_delete_on_terminate ? 1 : 0, 
'uuid': finalSpec.source_id, 
'boot_index': '0', 
'volume_size': finalSpec.vol_size 
} 
); 
} 
} 
function setFinalSpecBootFromVolumeDevice(finalSpec, sourceType) { 
finalSpec.block_device_mapping = {}; 
finalSpec.block_device_mapping[finalSpec.vol_device_name] = [ 
finalSpec.source_id, 
':', 
sourceType, 
'::', 
(finalSpec.vol_delete_on_terminate ? 1 : 0) 
].join(''); 
// Source ID must be empty for API 
finalSpec.source_id = ''; 
} 
// Nova Limits 
function onGetNovaLimits(data) { 
angular.extend(model.novaLimits, data.data); 
} 
// Metadata Definitions 
/** 
* Metadata definitions provide supplemental information in detail 
* rows and should not slow down any of the other load processes. 
* All code should be written to treat metadata definitions as 
* optional, because they are never guaranteed to exist. 
*/ 
function getMetadataDefinitions() { 
// Metadata definitions often apply to multiple 
// resource types. It is optimal to make a single 
// request for all desired resource types. 
var resourceTypes = { 
flavor: 'OS::Nova::Flavor', 
image: 'OS::Glance::Image', 
volume: 'OS::Cinder::Volumes' 
}; 
angular.forEach(resourceTypes, function (resourceType, key) { 
glanceAPI.getNamespaces({ 
'resource_type': resourceType 
}, true) 
.then(function (data) { 
var namespaces = data.data.items; 
// This will ensure that the metaDefs model object remains 
// unchanged until metadefs are fully loaded. Otherwise, 
// partial results are loaded and can result in some odd 
// display behavior. 
if(namespaces.length) { 
model.metadataDefs[key] = namespaces; 
} 
}); 
}); 
} 
return model; 
} 
]); 
})(); 

    Status 

回答

3

指定相關模塊,當你聲明自己的模塊所需要的陣列或[]參數,所以這應該只發生一次每個模塊。

第二個符號,沒有參數只是檢索模塊,以便您可以將控制器/服務/過濾器/ ...附加到它。

使用數組符號爲模塊的聲明,如果你想添加一些內容使用單一參數符號。

例如:

在app.module.js

//You want to make use of the ngRoute module, 
    //so you have to specify a dependency on it 
    angular.module('app', ['ngRoute']); 

你只會指定模塊的依賴性一次,你把它聲明。

在main.controller.js

//You want to add a controller to your module, so you want to retrieve your module 
angular.module('app').controller('mainCtrl', mainCtrl); 

function mainCtrl() { }; 

現在的角度將嘗試找到該名稱,而不是創建一個,當它沒有找到一個模塊,你會得到一些錯誤,這也解釋了你原來的問題。 每次你想添加一些東西到你的模塊時,你通常會這樣做。

請注意,您也可以通過在創建模塊時將模塊存儲在全局變量中,然後在想要添加內容時訪問該模塊,但正如您可能知道的那樣,創建全局變量是一個不好的做法。

+0

感謝,我得到的東西,但如果你給例子或教程,那麼這將是更好地理解.. – geeks

+0

@ NexusDuck,感謝我得到了給定的例子,但他們是如何使用這個https://github.com/openstack/horizo​​n/blob/stable/kilo/openstack_dashboard/static/dashboard/launch-instance/launch-instance.model.js#L15(請參閱突出顯示。 – geeks

+0

這只是一個文件,他們如果你看一下https://github.com/openstack/horizo​​n/blob/stable/kilo/openstack_dashboard/static/dashboard/launch-display.php,你可以添加一個工廠(如果你仔細看,你會看到module.factory) instance/launch-instance.js,你會看到他們聲明瞭他們的模塊重新依賴於ngSanitize –

1

面對角度錯誤是一種幸福,因爲它提供了控制檯中錯誤描述的鏈接。

從一個示例page這樣...

當定義沒有模塊依賴關係的模塊,依賴關係的數組應該被定義和空。

var myApp = angular.module('myApp', []);

要檢索進一步的配置以相同的模塊的引用,調用angular.module而不數組參數。

var myApp = angular.module('myApp');

+0

感謝您的回覆,您的回答聽起來像是我,您能否再次看到我更新了源代碼或此鏈接的問題並解釋他們如何使用https://github.com/openstack/horizo​​n/blob/stable/ kilo/openstack_dashboard/static/dashboard/launch-instance/launch-instance.model.js#L15 – geeks

+0

,因爲如果你去這裏 - https://github.com/openstack/horizo​​n/blob/stable/kilo/openstack_dashboard/static/儀表板/ launch-instance/launch-instance.js#L4 - 你會看到他們在模型中使用它之前已經定義了它。在這裏他們使用依賴數組。 –

+0

謝謝術士.. – geeks