AngularJS 是否有在 div 中为 属性 添加别名的语法?
Does AngularJS have a syntax to alias a property within a div?
这是一个奇怪的问题,但我的想法是:
假设我有一个复杂的 JSON 对象从 HTTP 调用返回并附加到 $scope
。像这样:
$scope.obj = {
user: {
id: 10,
name: { first: 'Joe', last: 'Smith' },
contact: {
home: {
street: '101 First St.',
city: 'Myville',
state: 'Jokelahoma',
zip: '98765'
},
email: 'joeshmoe@gmail.com',
phone: '+12345678901'
}
},
purchase_hist: [
{ item_id: 11004, date: 'Thu, 06 Aug 2015 13:51:17 GMT' },
{ item_id: 97020, date: 'Fri, 31 Jul 2015 18:57:57 GMT' }
]
}
现在,如果我想在 AngularJS 部分中显示购买历史概览,我可以这样做:
<table>
<tr ng-repeat="p in obj.purchase_hist">
<td>{{p.item_id}}</td>
<td>{{p.date}}</td>
</tr>
</table>
这种格式真正方便的地方(虽然它在这里用这么少的道具不是很明显)是所描述的购买别名为 p
。我不必做 obj.purchase_hist[0].item_id
,我可以做 p.item_id
.
但是当我去显示用户的家庭住址时呢?我真的必须这样做吗?:
<div>
<p>{{obj.user.contact.home.street}}</p>
<p>{{obj.user.contact.home.city}}</p>
<p>{{obj.user.contact.home.state}}</p>
<p>{{obj.user.contact.home.zip}}</p>
</div>
这真是冗长。我宁愿使用类似于 controller as ...
语法的东西,像这样:
<div ng-alias="obj.user.contact.home as uhome">
<p>{{uhome.street}}</p>
<p>{{uhome.city}}</p>
<p>{{uhome.state}}</p>
<p>{{uhome.zip}}</p>
</div>
AngularJS中有这样的东西吗?不幸的是,我不太能够在我的环境中使用插件,所以我专门寻找可以这样工作的 angular 核心的一部分。
谢谢!
<div ng-init="uhome = obj.user.contact.home">
<p>{{uhome.street}}</p>
<p>{{uhome.city}}</p>
<p>{{uhome.state}}</p>
<p>{{uhome.zip}}</p>
</div>
https://code.angularjs.org/1.3.16/docs/api/ng/directive/ngInit
据我所知,没有什么是真正简单的。
有一些黑客。您可以使用新控制器将对象重新映射到新范围
<div ng-controller="Ctrl as c" ng-init="c.makeAlias(obj.user.contact.home)">
<p>{{c.home}}</p>
</div>
其中 Ctrl 只是将 makeAlias
参数存储到它的范围内,作为 home
this.makeAlias(home) {
this.home = home;
}
另一个解决方案是使用 $scope.$watch
并将对象重新映射到更方便的对象。
我写了这个小指令,它允许你执行你想要的:
指令 ngAlias
(function(){
function ngAlias($compile) {
return {
restrict: "A",
link: function(scope, element, attrs) {
var args = attrs.ngAlias.split('as').map(function(elm){return elm.replace(/ /g,'')});
scope[args[0]] = '';
var dot = args[1].split('.');
var object = {};
dot.forEach(function(value, index){
index === 0
? object = scope[value]
: object = object[value] === null ? object[value] = {} : object[value];
});
console.log(object)
scope[args[0]] = object;
}
};
}
angular
.module('app')
.directive('ngAlias', ngAlias);
})();
例如,在控制器中设置对象
控制器
(function(){
function Controller($scope) {
$scope.obj = {
toto: {
nom: 'toto',
prenom: 'tata'
}
};
}
angular
.module('app', [])
.controller('ctrl', Controller);
})();
你可以使用它:
HTML
<body ng-app="app" ng-controller="ctrl">
<div ng-alias="toto as obj.toto">
{{toto.nom}}
</div>
</body>
我认为 Angular 不会为此类事情提供开箱即用的支持。但是您绝对可以将 Domain object.Convert 您的 http 响应创建到域对象中。在您的域对象中,您可以使用辅助方法来获取所需的信息。
例如,在您的情况下,您可以拥有这样的域对象
factory('User', function () {
return function (id,name, contact, purchase_hist) {
this.id = id;
this.name = name;
this.contact = contact;
this.purchase_hist = purchase_hist;
this.getContact = function(){
return this.contact.home;
};
};
})
您可以在您的控制器中使用此域对象
$scope.user = // domain object return from your service
在 html 你可以使用
{{user.getContact().street}}
您可以重新定义您的域以使事情 easier.It 可能是额外的工作。但是当你不得不再次做同样的事情时,again.One 可以享受这样写代码的乐趣
@PaulBoutes 提供了我需要的答案,他应该得到荣誉;我只是想根据他的回答添加我确定的指令版本。
app.directive('alias', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var splits = attrs['alias'].trim().split(/\s+as\s+/);
scope.$watch(splits[0], function(val) {
scope.$eval(splits[1]+'=('+splits[0]+')');
});
}
};
});
与 Paul 的基本思想相同,只是稍微清理了一下,并在空格等方面变得更加灵活。
用法示例:
<div data-alias="obj.user.contact.home as uhome">
<p>{{uhome.street}}</p>
<p>{{uhome.city}}</p>
<p>{{uhome.state}}</p>
<p>{{uhome.zip}}</p>
</div>
当然这里不乏可行的解决方案,但添加另一个也不会有什么坏处。
前几天我把它放在一起是为了节省我自己的打字时间并使我的 html 更容易阅读。它创建了一个新的子作用域,所以它不会用这些别名污染现有的作用域。它只是通过将父作用域的 属性 绑定到具有您指定的任何名称的新子作用域来工作。
app.directive('with', function() {
return {
restrict: 'A',
scope: true,
link: function(scope, element, attrs) {
if (attrs.as) {
scope[attrs.as] = scope.$eval(attrs.with);
} else {
angular.extend(scope, scope.$eval(attrs.with));
}
}
};
});
所以,与其这样做:
<div>{{some.deeply.nested.model.id}} - {{some.deeply.nested.model.name}}</div>
这样做:
<div with="some.deeply.nested.model" as="t">{{t.id}} - {{t.name}}</div>
或者,不使用 as
:
<div with="some.deeply.nested.model">{{id}} - {{name}}</div>
我刚刚遇到这个并测试了 ngAlias 指令,它可能工作正常也可能不工作,我不知道因为我遇到了问题,可能是由于其他一些不相关的错误,我决定这个更简单的方法:
<div ng-repeat="uhome in [obj.user.contact.home]">
<p>{{uhome.street}}</p>
<p>{{uhome.city}}</p>
<p>{{uhome.state}}</p>
<p>{{uhome.zip}}</p>
</div>
多田! "obj.user.contact.home" 现在是 "uhome" 的别名。我相信这个解决方案实际上也正是您问这个问题时想要的,因为它确实使用了 ng-repeat,因此具有 ng-repeat 的内置别名机制的所有好处。
这是一个奇怪的问题,但我的想法是:
假设我有一个复杂的 JSON 对象从 HTTP 调用返回并附加到 $scope
。像这样:
$scope.obj = {
user: {
id: 10,
name: { first: 'Joe', last: 'Smith' },
contact: {
home: {
street: '101 First St.',
city: 'Myville',
state: 'Jokelahoma',
zip: '98765'
},
email: 'joeshmoe@gmail.com',
phone: '+12345678901'
}
},
purchase_hist: [
{ item_id: 11004, date: 'Thu, 06 Aug 2015 13:51:17 GMT' },
{ item_id: 97020, date: 'Fri, 31 Jul 2015 18:57:57 GMT' }
]
}
现在,如果我想在 AngularJS 部分中显示购买历史概览,我可以这样做:
<table>
<tr ng-repeat="p in obj.purchase_hist">
<td>{{p.item_id}}</td>
<td>{{p.date}}</td>
</tr>
</table>
这种格式真正方便的地方(虽然它在这里用这么少的道具不是很明显)是所描述的购买别名为 p
。我不必做 obj.purchase_hist[0].item_id
,我可以做 p.item_id
.
但是当我去显示用户的家庭住址时呢?我真的必须这样做吗?:
<div>
<p>{{obj.user.contact.home.street}}</p>
<p>{{obj.user.contact.home.city}}</p>
<p>{{obj.user.contact.home.state}}</p>
<p>{{obj.user.contact.home.zip}}</p>
</div>
这真是冗长。我宁愿使用类似于 controller as ...
语法的东西,像这样:
<div ng-alias="obj.user.contact.home as uhome">
<p>{{uhome.street}}</p>
<p>{{uhome.city}}</p>
<p>{{uhome.state}}</p>
<p>{{uhome.zip}}</p>
</div>
AngularJS中有这样的东西吗?不幸的是,我不太能够在我的环境中使用插件,所以我专门寻找可以这样工作的 angular 核心的一部分。
谢谢!
<div ng-init="uhome = obj.user.contact.home">
<p>{{uhome.street}}</p>
<p>{{uhome.city}}</p>
<p>{{uhome.state}}</p>
<p>{{uhome.zip}}</p>
</div>
https://code.angularjs.org/1.3.16/docs/api/ng/directive/ngInit
据我所知,没有什么是真正简单的。 有一些黑客。您可以使用新控制器将对象重新映射到新范围
<div ng-controller="Ctrl as c" ng-init="c.makeAlias(obj.user.contact.home)">
<p>{{c.home}}</p>
</div>
其中 Ctrl 只是将 makeAlias
参数存储到它的范围内,作为 home
this.makeAlias(home) {
this.home = home;
}
另一个解决方案是使用 $scope.$watch
并将对象重新映射到更方便的对象。
我写了这个小指令,它允许你执行你想要的:
指令 ngAlias
(function(){
function ngAlias($compile) {
return {
restrict: "A",
link: function(scope, element, attrs) {
var args = attrs.ngAlias.split('as').map(function(elm){return elm.replace(/ /g,'')});
scope[args[0]] = '';
var dot = args[1].split('.');
var object = {};
dot.forEach(function(value, index){
index === 0
? object = scope[value]
: object = object[value] === null ? object[value] = {} : object[value];
});
console.log(object)
scope[args[0]] = object;
}
};
}
angular
.module('app')
.directive('ngAlias', ngAlias);
})();
例如,在控制器中设置对象
控制器
(function(){
function Controller($scope) {
$scope.obj = {
toto: {
nom: 'toto',
prenom: 'tata'
}
};
}
angular
.module('app', [])
.controller('ctrl', Controller);
})();
你可以使用它:
HTML
<body ng-app="app" ng-controller="ctrl">
<div ng-alias="toto as obj.toto">
{{toto.nom}}
</div>
</body>
我认为 Angular 不会为此类事情提供开箱即用的支持。但是您绝对可以将 Domain object.Convert 您的 http 响应创建到域对象中。在您的域对象中,您可以使用辅助方法来获取所需的信息。 例如,在您的情况下,您可以拥有这样的域对象
factory('User', function () {
return function (id,name, contact, purchase_hist) {
this.id = id;
this.name = name;
this.contact = contact;
this.purchase_hist = purchase_hist;
this.getContact = function(){
return this.contact.home;
};
};
})
您可以在您的控制器中使用此域对象
$scope.user = // domain object return from your service
在 html 你可以使用
{{user.getContact().street}}
您可以重新定义您的域以使事情 easier.It 可能是额外的工作。但是当你不得不再次做同样的事情时,again.One 可以享受这样写代码的乐趣
@PaulBoutes 提供了我需要的答案,他应该得到荣誉;我只是想根据他的回答添加我确定的指令版本。
app.directive('alias', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var splits = attrs['alias'].trim().split(/\s+as\s+/);
scope.$watch(splits[0], function(val) {
scope.$eval(splits[1]+'=('+splits[0]+')');
});
}
};
});
与 Paul 的基本思想相同,只是稍微清理了一下,并在空格等方面变得更加灵活。
用法示例:
<div data-alias="obj.user.contact.home as uhome">
<p>{{uhome.street}}</p>
<p>{{uhome.city}}</p>
<p>{{uhome.state}}</p>
<p>{{uhome.zip}}</p>
</div>
当然这里不乏可行的解决方案,但添加另一个也不会有什么坏处。
前几天我把它放在一起是为了节省我自己的打字时间并使我的 html 更容易阅读。它创建了一个新的子作用域,所以它不会用这些别名污染现有的作用域。它只是通过将父作用域的 属性 绑定到具有您指定的任何名称的新子作用域来工作。
app.directive('with', function() {
return {
restrict: 'A',
scope: true,
link: function(scope, element, attrs) {
if (attrs.as) {
scope[attrs.as] = scope.$eval(attrs.with);
} else {
angular.extend(scope, scope.$eval(attrs.with));
}
}
};
});
所以,与其这样做:
<div>{{some.deeply.nested.model.id}} - {{some.deeply.nested.model.name}}</div>
这样做:
<div with="some.deeply.nested.model" as="t">{{t.id}} - {{t.name}}</div>
或者,不使用 as
:
<div with="some.deeply.nested.model">{{id}} - {{name}}</div>
我刚刚遇到这个并测试了 ngAlias 指令,它可能工作正常也可能不工作,我不知道因为我遇到了问题,可能是由于其他一些不相关的错误,我决定这个更简单的方法:
<div ng-repeat="uhome in [obj.user.contact.home]">
<p>{{uhome.street}}</p>
<p>{{uhome.city}}</p>
<p>{{uhome.state}}</p>
<p>{{uhome.zip}}</p>
</div>
多田! "obj.user.contact.home" 现在是 "uhome" 的别名。我相信这个解决方案实际上也正是您问这个问题时想要的,因为它确实使用了 ng-repeat,因此具有 ng-repeat 的内置别名机制的所有好处。