我有一个控制器,我写的是我在我的应用中使用ng-include
和ng-repeat
的多个位置,如下所示:
<div
ng-repeat="item in items"
ng-include="'item.html'"
ng-controller="ItemController"
></div>
在控制器/模板中,我希望item
值存在,并且整个事情是围绕这个想法构建的。但是,现在我需要以稍微不同的方式使用控制器,而不需要ng-repeat
,但仍然需要能够传入item
。我看到ng-init
并认为它可以做我需要的事情,就像这样:
<div
ng-init="item = leftItem"
ng-include="'item.html'"
ng-controller="ItemController"
></div>
<div
ng-init="item = rightItem"
ng-include="'item.html'"
ng-controller="ItemController"
></div>
但这似乎不起作用。任何人都有任何想法如何在像这样的单一实例中传入范围的变量?
编辑:
上面的控制器加载leftItem
和rightItem
值,如下所示:
.controller('MainController', function($scope, ItemModel) {
ItemModel.loadItems()
.then(function(items) {
$scope.$apply(function() {
$scope.leftItem = items.left;
$scope.rightItem = items.right;
});
});
});
答案 0 :(得分:33)
您可以使用onload
提供的ngInclude
属性来执行此操作:
<div ng-include="'item.html'"
ng-controller="ItemController"
onload="item = rightItem">
</div>
修改强>
尝试在父范围内执行类似的操作:
$scope.dataHolder = {};
然后,当收到异步数据时,将数据存储在dataHolder
:
$scope.dataHolder.leftItem = items.leftItem;
$scope.dataHolder.rightItem = items.rightItem;
现在,当ng-include
加载模板时,它将创建一个继承父项属性的子作用域。因此$scope.dataHolder
将在此子范围中定义(最初作为空对象)。但是当收到异步数据时,对空对象的引用应该包含新接收的数据。
答案 1 :(得分:31)
晚会,但有一点角色&#39; hack&#39;在没有实施哑指令的情况下实现这一目标。
添加一个内置指令,可以扩展控制器的范围(例如ng-if),无论你在哪里使用ng-include,实际上都可以让你为所有包含的范围隔离变量名。
所以:
using System;
using System.Linq;
using System.Security.Cryptography;
using Org.BouncyCastle.Asn1;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
byte[] data = Convert.FromBase64String("dGF0b0Bmcm9td2luMzIuY29t");
byte[] signature = Convert.FromBase64String("lWKRRgWBA2lBAfUvBS+54s9kmHTH3nJwcvYYmjCg5QpWQ9joY7Rzpq0zZjOhyxASXoAN4Vz8+mqSqPWi/4DFH7947ZWZSbopPfxiI7jjDRMAVymG0B+dRVjiMow48ZvhgP/FGSZqeLAei77Z0aAmwN2TBxkClqBpt9uy+nkI7V/TJGAbbLcWfiPWNVOGsU0smoFDQLlJjkocahNSOqjj+9PPFVqbc/VVHQWsSoq1ZxtCPILFwPCCtUCDITXrU/riGMFJ282p/3rfhDJKYis9/izR98/zgBLRoCew8zu8Za4UNWaHaR3HP/6voQI2NiVSKtss1VjvwjwXYIOh56yeSw==");
byte[] publicKey = Convert.FromBase64String("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp6HzbSgZPkJPfZJWydFAKdzUWlQcGHCTZhghg8HwHOfRZp3QZ/iiDORVzdIlW6XYPz76aAn8Nxm/v4NbsQsFPbwIcc7CPOJe21VT+7f6ocZ4kef0dqxUOGuK1FynrqzsAeYoaeTW+w/HElXODOEzZs3CfyE3d4hy3TTM/mVyQGV1FO/hHWB/zXq7ryQ8hXP/ueJimmJvitB7UweemRxvEYfVx52VVAgzg1RqVWeRj8L/obfm0lwQtIAHdDOnIi/cwpsyKQNikjMsf4dFgt14fcOgFdSG06jB840GnOsRZM04CWZQ9ttwAvoNGK/zjriRYGySQ4Ey0K0l5G3UVr56mQIDAQAB");
byte[] hash;
using (SHA256 sha256 = SHA256.Create())
{
hash = sha256.ComputeHash(data);
}
bool b = false;
var rsaParam = GetPublicKeyRSAParameters(publicKey);
using (var rsa = new RSACryptoServiceProvider())
{
// Import public key
rsa.ImportParameters(rsaParam);
// Create signature verifier with the rsa key
var signatureDeformatter = new RSAPKCS1SignatureDeformatter(rsa);
// Set the hash algorithm to SHA256.
signatureDeformatter.SetHashAlgorithm("SHA256");
b = signatureDeformatter.VerifySignature(hash, signature);
}
}
public static RSAParameters GetPublicKeyRSAParameters(byte[] subjectPublicKeyInfoBytes)
{
var publicKeyObject = (DerSequence)Asn1Object.FromByteArray(subjectPublicKeyInfoBytes);
var rsaPublicKeyParametersBitString = (DerBitString)publicKeyObject[1];
var rsaPublicKeyParametersObject = (DerSequence)Asn1Object.FromByteArray(rsaPublicKeyParametersBitString.GetBytes());
var modulus = ((DerInteger)rsaPublicKeyParametersObject[0]).Value.ToByteArray().Skip(1).ToArray();
var exponent = ((DerInteger)rsaPublicKeyParametersObject[1]).Value.ToByteArray();
return new RSAParameters() { Modulus = modulus, Exponent = exponent };
}
}
}
然后,您可以使用不同的项目将模板item.html多次绑定到项目变量。
Here is a plunker to achieve what you want
问题是项目在控制器范围内不断变化,只保留对每个onload指令中擦除的项目变量的一个引用。
引入扩展当前范围的指令,让您拥有所有ng-include的隔离范围。 因此,项目引用在所有扩展范围内都被保留并且是唯一的。
答案 2 :(得分:17)
我最终将其重写为指令并使用
绑定范围内的所需值scope: {
item: '='
}
答案 3 :(得分:11)
LOVE @ Tanin的回答。以一种非常优雅的方式同时解决以及许多问题。对于那些不喜欢我的人来说,不知道Coffeescript,这里是javascript ...
注意:由于我太难理解的原因,此代码要求您引用模板名称一次,而不是ng-include要求两次引用您的模板名称,即。 -(void) fetchContacts
{
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted == YES) {
//keys with fetching properties
NSArray *keys = @[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey];
NSString *containerId = store.defaultContainerIdentifier;
NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId];
NSError *error;
NSArray *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
if (error) {
NSLog(@"error fetching contacts %@", error);
} else {
NSString *phone;
NSString *fullName;
NSString *firstName;
NSString *lastName;
UIImage *profileImage;
NSMutableArray *contactNumbersArray;
for (CNContact *contact in cnContacts) {
// copy data to my custom Contacts class.
firstName = contact.givenName;
lastName = contact.familyName;
if (lastName == nil) {
fullName=[NSString stringWithFormat:@"%@",firstName];
}else if (firstName == nil){
fullName=[NSString stringWithFormat:@"%@",lastName];
}
else{
fullName=[NSString stringWithFormat:@"%@ %@",firstName,lastName];
}
UIImage *image = [UIImage imageWithData:contact.imageData];
if (image != nil) {
profileImage = image;
}else{
profileImage = [UIImage imageNamed:@"acc_sett.png "];
}
for (CNLabeledValue *label in contact.phoneNumbers) {
phone = [label.value stringValue];
if ([phone length] > 0) {
[contactNumbersArray addObject:phone];
}
}
NSDictionary* personDict = [[NSDictionary alloc] initWithObjectsAndKeys: fullName,@"fullName",profileImage,@"userImage",phone,@"PhoneNumbers", nil];
[_Contacts addObject:personDict];
NSLog(@"%@",phone);
NSLog(@"%@",fullName);
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.contacttableview reloadData];
});
}
}
}];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [_Contacts count];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary* personDict = [_Contacts objectAtIndex:indexPath.row];
UITableViewCell *cell = nil;
cell = [_contacttableview dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cell"];
}
cell.imageView.image = [personDict objectForKey:@"userImage"];
cell.textLabel.text = [personDict objectForKey:@"fullName"];
cell.detailTextLabel.text = [personDict objectForKey:@"phoneNumbers"];
return cell;
}
代替<div ng-include-template="template-name.html" ... >
<div ng-include-template="'template-name.html'" ... >
答案 4 :(得分:10)
使用onload不是一个干净的解决方案,因为它会占用全局范围。如果你有更复杂的东西,它将开始失败。
ng-include不是可重用的,因为它可以访问全局范围。这有点奇怪。
上述情况并非如此。 ng-if with onload并不会影响全局范围
我们也不想为每种情况编写具体指令。
制作通用指令而不是ng-include是一种更清洁的解决方案。
理想用法如下:
<div ng-include-template="'item.html'" ng-include-variables="{ item: 'whatever' }"></div>
<div ng-include-template="'item.html'" ng-include-variables="{ item: variableWorksToo }"></div>
指令是:
.directive(
'ngIncludeTemplate'
() ->
{
templateUrl: (elem, attrs) -> attrs.ngIncludeTemplate
restrict: 'A'
scope: {
'ngIncludeVariables': '&'
}
link: (scope, elem, attrs) ->
vars = scope.ngIncludeVariables()
for key, value of vars
scope[key] = value
}
)
您可以看到该指令不使用全局范围。相反,它从ng-include-variables读取对象,并将这些成员添加到其自己的本地范围。
我希望这是你想要的;它干净而且通用。
答案 5 :(得分:4)
ng-init对此更好。
<div ng-include='myFile.html' ng-init="myObject = myCtrl.myObject; myOtherObject=myCtrl.myOtherObject"/>
答案 6 :(得分:3)
上述内容不适用于二级属性,例如<div ng-include-template=... ng-include-variables="{ id: var.id }">
。请注意var.id
。
更新指令(丑陋,但有效):
.directive('ngIncludeTemplate', function() {
return {
templateUrl: function(elem, attrs) { return attrs.ngIncludeTemplate; },
restrict: 'A',
scope: {
'ngIncludeVariables': '&'
},
link: function(scope, elem, attrs) {
var cache = scope.ngIncludeVariables();
Object.keys(cache).forEach(function(key) {
scope[key] = cache[key];
});
scope.$watch(
function() {
var val = scope.ngIncludeVariables();
if (angular.equals(val, cache)) {
return cache;
}
cache = val;
return val;
},
function(newValue, oldValue) {
if (!angular.equals(newValue, oldValue)) {
Object.keys(newValue).forEach(function(key) {
scope[key] = newValue[key];
});
}
}
);
}
};
});
答案 7 :(得分:1)
Maybe obvious update for Mike and Tanin answers - if you using inline templates as:
<script type="text/ng-template" id="partial">{{variable}}</script>
<div ng-include-template="'partial'" ng-include-variables="{variable: variable}"></div>
Then, in directive ngIncludeTemplate, replace
templateUrl: function(elem, attrs) { return attrs.ngIncludeTemplate; },
With
template: function(elem, attrs) { return document.getElementById(attrs.ngIncludeTemplate.split("'")[1]).innerHTML },