Ember update video sources, but not reflected in the browser

I have an ember application with embedded resources in which I display a video. An external resource (video) simply displays all the videos. When you click a video, the embedded video resource is activated and the title / player is displayed.

This works great on the first click. A video appears and it plays. HOWEVER, when you click another video, the video of the attached resource is updated, and the DOMs <source> updated, but the OLD video continues to play! Why is this happening and how to fix it?

Working example in JSFiddle

+5
source share
5 answers

I would use a component to create a video player and wrap the logic of the rederder in the component.

The component would look like

 App.VideoPlayerComponent = Ember.Component.extend({ src: null, rerenderPlayer: function(){ if(this.$()) { Ember.run.debounce(this, this.rerender, 200); } }, srcObserver: function(){ this.rerenderPlayer(); }.observes('src') }); 

and the component template will look like

 <script type="text/x-handlebars" data-template-name="components/video-player"> <video controls> <source {{bind-attr src=src}} type = "video/mp4"></source> </video> </script> 

Then you can just reference the component in your template, for example

 <script type="text/x-handlebars" data-template-name="video"> <h2>{{title}}</h2> {{video-player src=src}} </script> 

Here you can see the working disk: http://emberjs.jsbin.com/fehipa/2/edit


As a bonus. If you created a video player component, you can also pause and play the video in the component. So you can use the fully used video player for use anywhere in your application.

+3
source

If you move the {{bind-attr src="src"}} element from the <source> element to the <video> element, it just works without hacks.

your code will change from:

 <video controls> <source {{bind-attr src="src"}} type = "video/mp4"></source> </video> 

to

 <video controls {{bind-attr src="src"}}></video> 

Working example: http://jsfiddle.net/jfmzwhxx/

+1
source

This is a little ugly, but it can be achieved by rendering the view. Add the following code:

 App.VideoRoute = Ember.Route.extend({ oldVideoId: null, afterModel: function (resolvedModel) { if (this.get('oldVideoId') !== resolvedModel.id) { this.set('oldVideoId', resolvedModel.id); $.each(Ember.View.views, function( i, view ) { if (view.renderedName === "videos"){ view.rerender(); } }); } } }); 

Working script

0
source

I would take a similar approach to @AlliterativeAlice, but I would definitely not recommend performing this operation at the route level. This problem is a consequence of the security of the DOM and, therefore, is the task for presentation. It’s best to set up an observer in your view class and call the rederder from there. For instance:.

 App.VideoView = Ember.View.extend({ _didChangeVideoSrc: function() { // Make the view is still in the DOM if(this.$()) { this.rerender(); } }.observes('controller.src') }); 

I also updated my script to make this work: http://jsfiddle.net/rverobx9/2/

0
source

While answers suggesting re-rendering in some way may solve your problem, if you have access to the player's API, it would be nice to see if the video stops stopping in your view's willDestroyElement to fix it.

In addition, you may have your video player, which is a component of Ember, which provides good configuration, shutdown and update:

 App.VideoPlayerComponent = Ember.Component.extend({ source: null, // used in the template using that component isPlayerReady: false, // used to know internally if the player is ready setupPlayer: (function(){ // somehow setup the video player if needed // (if Flash player for example, make the flash detection and whatever) // once ready, trigger our `videoPlayerReady` event this.set('isPlayerReady', true); this.trigger('videoPlayerReady'); }).on('didInsertElement'), updatePlayerSource: (function(){ // start playing if we have a source and our player is ready if ( this.get('isPlayerReady') && this.get('source') ) { // replace with the correct js to start the video this.$('.class-of-player').videoPlay(this.get('source')); } }).observes('source').on('videoPlayerReady'), teardownSource: (function(){ // stop playing if our player is ready since our source is going to change if ( this.get('source') && this.get('isPlayerReady') ) { // replace with the correct js to stop the player this.$('.class-of-player').videoStop(); } }).observesBefore('source'), teardownPlayer: (function(){ // teardown the player somehow (do the opposite of what is setup in `setupPlayer`) // then register that our player isn't ready this.set('isPlayerReady', false); }).on('willDestroyElement') }); 

This will allow you to make sure that everything is correctly configured and worked correctly, and since this is a component that you can reuse, it will be very easy to have a backup copy for a flash player, for example. Then, no matter what you do and correct things related to the player, he will be in this component, and you just need to replace part of your template with a player:

 {{video-player source=ctrl.videoUrl}} 
0
source

Source: https://habr.com/ru/post/1202042/


All Articles