我似乎误解了$ observe的工作原理。从以下示例(plunker link)。
HTML
<html ng-app="record">
<head>
<script data-require="angular.js@*" data-semver="1.2.0-rc2" src="http://code.angularjs.org/1.2.0-rc.2/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="IndexController">
<input type="text" value="{{src}}"/>
<input type="text" value="{{RecordAddress}}"/>
<input type="text" value="{{FlashVars}}"/>
<input type="button" ng-click="handleClick()" value="click me"/>
<record src="{{src}}"></record>
</body>
</html>
JS
angular.module('record',[])
.controller("IndexController", function($scope)
{
console.log('controller called')
$scope.handleClick = function()
{
console.log('handleClick - called');
$scope.RecordAddress = 'rtmp://thisIsAnAddress';
$scope.FlashVars = 'userid=SomeId&filename=http://localhost/Content/ThisIsAnAddress/player.swf&mediaFormat=_video.mp4&mediaServerAddress=rtmp://ThisIsAnAddress&culture=en-GB'
$scope.src = $scope.RecordAddress+ '`' + $scope.FlashVars;
}
})
.directive('record', function ($location) {
return {
restrict: 'E',
scope: {
current: '=current'
},
link: function ($scope, element, attr) {
console.log('record directive - called');
console.log(attr);
attr.$observe('src', function(value)
{
console.log('record observe callback called!');
console.log('The value is: '+ value);
if(value && value !='recordValues')
{
var values = value.split('`');
console.log('video values:')
console.log(values);
element.html('<object position="relative" width="519px" height="520px" data="'+values[0]+'" type="application/x-shockwave-flash"><param name="FlashVars" value="'+values[1]+'" /><param name="AllowScriptAccess" value="always" /></object>');
}
else
{
element.html("<div>Please wait</div>")
}
}
);
}
}
});
我希望在单击按钮时呈现“对象”,而不是在设置未准备好时应该出现的“请稍候”。但是,当“src”属性看似更新时,不会调用它。有人可以向我解释为什么这个例子不起作用吗?
答案 0 :(得分:4)
对于具有独立范围的指令,您应用指令的元素不会继承父级的范围。因此,您不会看到任何{{src}}
变量 - 它将始终为空。
使用隔离范围的指令属性,您可以通过两种方式与外部世界进行通信:
src="{{$parent.src}}"
,但这有点hackish scope: {
src: '@src'
}
然后以下代码将起作用:
$attrs.$observe('src', function(value) {
//some action
});
答案 1 :(得分:2)
我认为你有一些事情在进行,这总是有趣的调试。我怀疑$ watch可能对你更好。但是,使用element.html()
调用会覆盖您尝试观看的html中的变量。
我做了一些更改(都包含在你的指令中)并且下面有一些工作代码(我添加了一个模板来放置你的消息 - 当然还有其他各种方法来做同样的事情)。
directive('record', function ($location,$sce) {
return {
restrict: 'E',
template: '<div ng-bind-html="trustedMsg"></div>',
link: function ($scope, element, attr) {
console.log('record directive - called');
console.log(attr);
$scope.$watch('src', function(value)
{
console.log('record observe callback called!');
console.log('The value is: '+ value);
if(value && value !='recordValues')
{
var values = value.split('`');
console.log('video values:')
console.log(values);
$scope.message='<object position="relative" width="519px" height="520px" data="'+values[0]+'" type="application/x-shockwave-flash"><param name="FlashVars" value="'+values[1]+'" /><param name="AllowScriptAccess" value="always" /></object>';
$scope.trustedMsg = $sce.trustAsHtml($scope.message);
}
else
{
$scope.message="<div>Please wait</div>";
$scope.trustedMsg = $sce.trustAsHtml($scope.message);
}
}
);
}
}
});
另外,如果您更喜欢坚持使用attr。$ observe call,那么您可以更改您的html:
<record src='{{src}}'></record>
到:
<record src='src'></record>
编辑:我更新(并测试)了代码,因此消息现在支持html,就像您的代码一样。 (http://plnkr.co/edit/K18Djio1NfSaHIWOXpeJ)
答案 2 :(得分:1)
我认为你误用了$ observe函数,虽然我可能只是不理解你想要做的100%。我认为更好的方法是在控制器中的src
上设置适当的$scope
值,然后使用$watch
检测对该值的更改。以下是我建议你这样做的方法:
在您的控制器中:
$scope.handleClick = function(){
console.log('handleClick - called');
$scope.RecordAddress = 'rtmp://thisIsAnAddress';
$scope.FlashVars = 'userid=SomeId&filena...';
//Now set the src on the scope as you already had:
$scope.source = $scope.RecordAddress+ '`' + $scope.FlashVars;
}
在你的html视图中:
<!-- remove the binding braces so you're just passing a regular attribute -->
<record src="source"></record>
在你的指令中:
//add a simple update function (for cleanliness)
function update(value){
if(value && value !='recordValues'){
var values = value.split('`');
element.html('INSERT YOUR LONG HTML STRING HERE');
}else{
element.html("<div>Please wait</div>")
}
}
// get any initial value for the 'source' variable
var value = scope.$eval(attrs.src); // this will return the scope's source variable
if(value) update(value);
// watch for any changes to that variable on the scope
scope.$watch(attrs.src, update);
注意:即使我相信上面的代码可以满足你的需求,但我认为它并不是最好的方法。您实际上是从控制器向指令传递了两个值:1)RecordAddress
和2)FlashVars
。我建议您为record
元素添加两个单独的属性:
<record address="addr" flash-vars="flashVars"></record>
然后你将它们与你的指令分开绑定:
function update(addr, flashVars){ ... }
scope.$eval(addrs.address, function(value){ ... });
scope.$eval(addrs.flashVars, function(value){ ... });
scope.$watch(addrs.address, ...);
scope.$watch(addrs.flashVars, ...);
这样可以避免必须拆分指令中的值。