0

home.html

<videodata></videodata>

videoctrl.js

$rootScope.cameraRTSPUrl = obj.objUrl;

directive.js

directive - myApp.directive('videodata', function() {
    return {
        restrict: 'EA',
        scope : true ,
        link: function(scope, element, attrs) {

            element.replaceWith('<object classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921" '+
                                    'codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab" '+
                                    'id="vlc" events="True"> '+
                                    '<embed id="123" type="application/x-google-vlc-plugin" version="VideoLAN.VLCPlugin.2" autoplay="yes" '+
                                    'loop="no" width="800" height="600" target="'+scope.cameraRTSPUrl+'"> '+
                                '</object>');

        }
    };
});

The above code works and rendered HTML is below

    <object events="True" id="vlc" 
        codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab" 
        classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921">
        <embed width="800" height="600" target="rtsp://localhost/media/media.amp" loop="no" autoplay="yes" 
        version="VideoLAN.VLCPlugin.2" type="application/x-google-vlc-plugin" id="123">
    </object>   
  1. The code works with element.replaceWith but is this the correct way to replace HTML using custom directive ?
  2. How do I use transclude: true, property in order to replace my HTML ?

P.S. I am using scope.cameraRTSPUrl value inside link function.

3
  • 1
    Use replace : true and use template : <your html> in return object. That might help. Sorry, but I did not get what you want to achieve. In order to transcendent inner html of the directive, you also need to set transclude:true and use ng-transclude directive in your template. docs.angularjs.org/api/ng/directive/ngTransclude Commented Jun 28, 2016 at 12:18
  • Downvoter pls explain. I am able to achieve the desired result but want to know the best way for the same. Commented Jun 28, 2016 at 12:21
  • Can you please tell me what results you want to achieve? Commented Jun 28, 2016 at 13:07

2 Answers 2

3

The code works with element.replaceWith but is this the correct way to replace HTML using custom directive ?

Nope. It is more or less the worst possible wrong way, because it prevents any Angular data or event binding or really any of the other reasons Angular is worth using; you're dumping a blob of uncompiled HTML into the page that Angular doesn't really know about.

You never want to modify the DOM directly in Angular. If you do modify the DOM directly, what you add should almost always be $compiled first so Angular can find any data or event bindings inside it. (Experienced Angular devs may take issue with my use of the word "never". It's true that there are some cases where this advice doesn't apply, but as a new-to-Angular developer you're unlikely to run into them for quite a while. Best practice is to let Angular do the work until you have a good understanding of what it's doing. And then still let Angular do most of the work, because that's what it's good at.)

For your example, the way you've done it, the ng-hide wont work, and if the value of scope.cameraRTSPUrl changes, that change will not be reflected in the UI. Instead, use a directive template or templateUrl, so you'll get access to Angular's data binding:

myApp.directive('videodata', function() {
    return {
        restrict: 'EA',
        scope : true,
        replace: true,
        templateUrl: 'templates/foo.html',
        link: function(scope, element, attrs) {
            scope.cameraRTSPUrl = "someGeneratedValue.mov"; // could passed into the directive via an attribute or parent data binding, for example
        }
    };
});

foo.html:

<div ng-hide="StartPlay" id="streamingarea">
    <object events="True" id="vlc" codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab" 
        classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921">
        <embed width="800" height="600" target="{{cameraRTSPUrl}}" loop="no" autoplay="yes" 
        version="VideoLAN.VLCPlugin.2" type="application/x-google-vlc-plugin" id="123">
    </object>   
</div>

Now you can trigger the ng-hide by just changing the truthiness of scope.StartPlay, and changes to scope.cameraRTSPUrl will appear in the DOM automatically.

How do I use transclude: true, property in order to replace my HTML?

That's not really what transclude is for. Transclude allows you to create directives that contain html not generated from within that directive (the part that comes from elsewhere is the "transcluded" bit; the transclude directive is a wrapper around that transcluded html.)

Sign up to request clarification or add additional context in comments.

9 Comments

Thanks for the detailed explanation and altering my code to above works and changes the target, but unfortunately my video does not play. This is was the issue initially and then I resorted to replaceWith method which plays video when target changes. How do I overcome this ?
Could be a few things. How are you passing the target url to the directive? (It's possible that the directive is being drawn with an empty target URL, the video 'autoplay' fails, then in the next digest you set cameraRTSPUrl -- if that's the case the easiest fix would probably be to trigger the video playback from within the link function rather than depending on autoplay.) If that guess isn't right, this probably rates a new separate question...
User will drag the video link and place it on a div streamingarea. Before dragging the url, the generated html is <div ng-hide="StartPlay" id="streamingarea" class="ng-hide"> <object classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921" codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab" id="vlc" events="True"> <embed width="800" height="600" id="123" type="application/x-google-vlc-plugin" version="VideoLAN.VLCPlugin.2" autoplay="yes" loop="no" target=""> </object> </div>.
After directive usage and target is set, html set is, <div ng-hide="StartPlay" id="streamingarea" class=""> <object classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921" codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab" id="vlc" events="True"> <embed width="800" height="600" id="123" type="application/x-google-vlc-plugin" version="VideoLAN.VLCPlugin.2" autoplay="yes" loop="no" target="rtsp://10.103.3.172/axis-media/media.amp"> </object> </div> How do I trigger video playback from within the link function rather than depending on autoplay ?
On further analysing, I found that replacing the whole embed html only then video starts playing. Changing its target ot autoplay option does not have any impact and video does not load. how do I replace the whole html using your solution ? Ref - stackoverflow.com/questions/10629238/…
|
0
Best way is to use template

template: 'Name: {{customer.name}} Address: {{customer.address}}'

 myApp.directive('videodata', function() {
    return {
        restrict: 'EA',
        scope : true ,
        link: function(scope, element, attrs) {
        template: '<object classid="clsid:9BE31822-FDAD-461B-AD51-BE1D1C159921" '+
                                    'codebase="http://downloads.videolan.org/pub/videolan/vlc/latest/win32/axvlc.cab" '+
                                    'id="vlc" events="True"> '+
                                    '<embed id="123" type="application/x-google-vlc-plugin" version="VideoLAN.VLCPlugin.2" autoplay="yes" '+
                                    'loop="no" width="800" height="600" target="'+scope.cameraRTSPUrl+'"> '+
                                '</object>'
        }
    };
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.