making changes to a {{ variable }} within the directive's template

I am having trouble understanding how to properly set a {{ variable }} in my directive template. Currently, the only way I can update it is by using $scope.$apply(), specifically for updating the current-time text in a video player.

You can view my code example on JSFiddle here with the usage of $scope.$apply() http://jsfiddle.net/ntdyp4oe/

In my directive, I am trying to find a way to update {{ currentTime }} without relying on $scope.$apply()

angular.module('canvas-video',[]).directive('canvasVideo', function($compile)
{
  return {
    restrict: 'E',
    replace:true,
    template:['',
      '<div id="canvas-video">',
        '<canvas id="canvas" ng-click="togglePlayback()" width="{{ width }}" height="{{ height }}"></canvas>',
        '<video src="{{ src }}" id="player"></video>',
        '<div id="controls">',
          '<div class="transport"><input id="slider" type="range" min="0" max="100" value="0" step="1"></div>',
          '<span class="current-time">{{ currentTime }}</span> | <span class="total-time">{{ totalTime }}</span>',
        '</div>',
      '</div>'
    ].join(''),
    scope: {
      src: '=',
      width: '=',
      height: '=',
      autoplay: '=?'
    },
    compile: function(element, attributes)
    {
      return {
        pre: function(scope, element, attributes)
        {
          if (!attributes.autoplay) attributes.autoplay = true;
          scope.currentTime = '00:00:00';
          scope.totalTime   = '00:00:00';
        },
        post: function(scope, element, attributes)
        {

        }
      }
    },
    controller: function($scope, $element, $attrs)
    {
      var canvas      = angular.element('canvas')[0];
      var ctx         = canvas.getContext('2d');
      var player      = angular.element('video')[0];
      player.autoplay = ($attrs.autoplay == 'false') ? 0 : 1;

      $scope.togglePlayback = function()
      {
        (player.paused) ? player.play() : player.pause();
      };

      $scope.renderPlayer = function()
      {
        var $this = this;
        $attrs.width = player.videoWidth;
        $attrs.height = player.videoHeight;
        canvas.setAttribute('width', $attrs.width);
        canvas.setAttribute('height', $attrs.height);
        $scope.totalTime = $scope.timecode(player.duration);

        (function loop()
        {
          if (!$this.paused && !$this.ended)
          {
            ctx.drawImage($this, 0,0, $attrs.width, $attrs.height);
            window.requestAnimationFrame(loop);
          }
        })();
      };

      //-- This section is where a lot of $apply calls are made
      //-- and doesn't work without it
      $scope.renderTime = function()
      {
        $scope.$apply(function()
        {
          $scope.currentTime = $scope.timecode(player.currentTime);
        });
      };

      $scope.timecode = function(seconds)
      {
        var minutes          = Math.floor(seconds/60);
        var remainingSec     = seconds % 60;
        var remainingMinutes = minutes % 60;
        var hours            = Math.floor(minutes/60);
        var floatSeconds     = Math.floor((remainingSec - Math.floor(remainingSec)) * 100);
        remainingSec         = Math.floor(remainingSec);
        return $scope.getTwoDigits(hours) + ":" + $scope.getTwoDigits(remainingMinutes) + ":" + $scope.getTwoDigits(remainingSec);
      };

      $scope.getTwoDigits = function(number)
      {
        return (number < 10) ? "0" + number : number;
      };

      player.addEventListener('timeupdate', $scope.renderTime);
      player.addEventListener('play', $scope.renderPlayer);
    }
  }
});

Answer №1

Make sure to always utilize the $apply() function for any events that modify the scope outside of the angular core framework. This informs angular to update the view accordingly.

When dealing with events controlled by core directives like ng-click, Angular automatically triggers $apply().

If your DOM listeners are not part of a directive, consider using $timeout to prevent potential clashes with ongoing digest cycles.

By using $timeout, Angular will handle invoking $apply internally if there are active digest processes taking place.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Obtaining the value of a command argument with JavaScript in ASP.NET

<asp:LinkButton ID="lnkprogress" runat="server" class="label label-info" BackColor="#589FC2" CommandArgument='<%#Eval("BookingId")%>' OnClientClick="jk();" >In progress</asp:LinkButton> This LinkButton is present in a repeat ...

Contentful - Unfortunately, this does not meet the criteria for valid JSON

https://i.sstatic.net/CLsT1.jpg My content model includes a field that holds a JSON object. However, when I attempt to input an array into this field, I receive an error stating This is not valid JSON. https://i.sstatic.net/uOVK6.png In another screensh ...

Differences between MobX local state and global state

I am currently working on a React project using mobx to manage the application state. For dump components that interact with external data sources (such as ajax calls, filtering or mapping arrays), I simply manipulate the data in those components. Howeve ...

I'm puzzled as to why my login isn't functioning unless I had previously signed up

I'm encountering an issue with logging in an existing user and displaying their name on the navbar. The error occurs when trying to access the username property of a null value. Interestingly, this error only occurs after signing up a new user and imm ...

The Alert Component fails to display when the same Error is triggered for the second time

In the midst of developing a Website using Nuxt.js (Vue.js), I've encountered an issue with my custom Alert Component. I designed a contact form on the site to trigger a specialized notification when users input incorrect data or omit required fields ...

Using AngularJS, it is possible to pass variable argument function calls in elements that are generated with

When using Bootstrap in conjunction with AngularJS components, it can become challenging to encapsulate inner Bootstrap elements within components. This is because the additional markup of the component itself added to the DOM may break CSS rules that rely ...

Selecting Laravel lists by month option

I'm encountering a problem here. The error message reads "Too few arguments to function App\Http\Controllers\ViewsController::OBviews(), 0 passed and exactly 1 expected" Here is my controller: public function OBviews($date) { ...

Observation - Various Parties Subscribing

Exploring RxJS and Observables is a new journey for me. I recently came across this informative tutorial -> I have a question: There are three components involved: OnePage: manipulates and displays the answers Service: manages the answers SecondPag ...

What is the process for retrieving the members of an ActiveDirectory 2 group through code?

I have been using ActiveDirectory2 to query LDAP in order to retrieve the users of a specific group, but unfortunately, I have not been successful so far. Here is an example of how I am using it: ad.authenticate(config.USERNAME, config.PASSWORD, function ...

The function `open` is not a valid prop for the `Dialog` component

Upon clicking an icon, a dialog box containing a form should appear for either adding a tab or deleting a specific tab. I have utilized reactjs, redux, and material-ui for the components. While I am able to display the dialog box when the icon is clicked, ...

Stop the repeated loading in Vue.js by implementing load-google-maps-api to ensure the map is only loaded

I am trying to dynamically load two instances of Google Maps on a single page but I keep encountering the following errors: You have included the Google Maps JavaScript API multiple times on this page. This may result in unexpected errors. Below is the ...

The Intersection of Angular JS and Web API Design

Currently working on designing an architecture that includes the following technologies: Angular JS 1.5 MVC 5.0/Web API. EF 6.0 Considering whether it is beneficial to have a single web project containing both Angular JS and Web API functionalities. We ...

Leverage the Redux store as the source of data for sending a POST request

For my React project, I designed an input interface and saved the data in a Redux state. Afterward, I set up a new action for making an API call to post the data. When using a constant value as the "data" parameter, everything functions properly. However ...

Guide on excluding certain words within a paragraph using PHP

In my database, there is a paragraph that looks like this: $str ="this is a paragraph i show shortly and when i click on the view more it will show completely for that i am using the ajax and retrieve it " I display it as follows: this is a paragrap ...

Switch up the Position of a Frame with jQuery

I'm attempting to cycle through an array of URLs in order to designate them as locations for a frame. The current setup I have can be found on this fiddle: var l = ['0', '1', '2', '3', '4', '5&ap ...

Every time I attempt to insert a background image into a div using jQuery, I am consistently faced with a 404 error message

When I hit enter in my search bar, a new div is created each time. However, I am struggling to assign a background image to the created div as I keep receiving a 404 error in the console. Below is the code snippet I'm working with: function appendToD ...

Constantly positioning the text cursor over the Textbox

I am currently in the process of developing a webpage that will feature only one text box for displaying information based on the input data provided. Our strategy involves utilizing either a Barcode Scanner or Magnetic Swipe as well as a Touch Screen Moni ...

{ error: unable to update backend column due to invalid input syntax for integer: "undefined"}

Using a combination of postgresql database, expressJs, and react, I am currently looking to update a specific column called inCart within my database. I have implemented a fetch function that utilizes a PUT method and is triggered by an onClick event. Howe ...

Disable timezone in my JavaScript random date generator

I have a code where I am trying to generate random dates, but the timezone is always included and I'm not sure how to remove it. Can someone assist me with this? I am new to coding, so any help would be greatly appreciated! Thank you. var startDate ...

HTML5 enables users to pick their preferred font style

In my JavaScript and HTML5 course, I am working on developing a website where users can choose the background color and decide between using SANS SERIF or SANS fonts. The background color selection feature is already functioning successfully -- var inputC ...