2013-10-14 177 views
1

我似乎誤解了$觀察是如何工作的。從以下示例(plunker link)。

HTML

<html ng-app="record"> 

    <head> 
    <script data-require="[email protected]*" 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

我想你應該看看這個太:http://docs.angularjs.org/api/ng.directive:ngSrc – unludo

回答

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。$觀察通話,那麼你可以在你的HTML代碼更改:

<record src='{{src}}'></record> 

到:

<record src='src'></record> 

編輯:我更新了(和測試)的代碼,以便消息現在支持HTML,因爲你的代碼一樣。 (http://plnkr.co/edit/K18Djio1NfSaHIWOXpeJ

+0

我很喜歡這個代碼,但$ sce只有1.2?在此之前我們做了什麼? – Quibblesome

+0

@Quibblesome,你說得對,默認包含$ sce,從1.2開始。但是在1.2之前有一個簡單的解決方案。在1.2之前,你可以使用'ng-bind-html-unsafe'(它在1.2中被刪除)。因此,對於1.2之前的版本,只需刪除對$ sce的引用,並使用'ng-bind-html-unsafe'而不是'ng-bind-html'(顯然,傳入'message'而不是'trustedMsg'你刪除了$ sce參考時刪除)) – KayakDave

+0

這太好了,謝謝你的反饋! – Quibblesome

1

我認爲你濫用$ observe功能,雖然我可能只是不明白你想要做的100%。我認爲一個更好的方法可以在您的控制器中爲$scope設置適當的src值,然後使用$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, ...); 

這將節省您不必拆分值在指令中。

+0

感謝您的評論! DaveKayak通過他的完整例子贏得了勝利,但我真的很想表達對在這裏幫助我的感激之情。 THANKEE !!!! :) – Quibblesome

4

對於具有隔離範圍的指令,您要應用指令的元素不會繼承父級的範圍。所以你不會在那裏看到任何{{src}}變量 - 它總是空的。

有兩種方法可以使用用於指令屬性的外部世界隔離範圍通信:

  • 使用src="{{$parent.src}}"但它是單向綁定
  • 有點hackish的
  • 使用@屬性映射
scope: { 
    src: '@src' 
} 

然後下面的代碼將工作:

$attrs.$observe('src', function(value) { 
    //some action 
}); 
+0

對不起,我沒有選擇這個答案,但KayakDave創建了一個完整的示例。雖然我喜歡你,但還是教給我更多關於孤立範圍的東西。範圍聲明中src的「複製」非常酷,我不知道它是如何工作的,所以我想單獨表達我的感謝。 :) – Quibblesome

+1

當然,但我真的認爲,在你的情況下,你應該使用$觀察,因爲'src'只有一種方法綁定在那裏。你不要將它從指令改回「外部世界」。同時$觀察比$ watch快一點。 – kseb