You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AngularJS与Rails集成时$scope未识别及剩余时间获取异常问题

Hey there! Let's work through this problem step by step—we'll fix that "undefined" issue and sort out the negative remaining time too.

First: Why does $scope.remainingTime show as undefined in your controller, but appear in console.log($scope)?

This almost always boils down to timing or how you're passing data from Rails to Angular:

  • If you're initializing remainingTime asynchronously (like via an API call, or relying on Rails to inject the value after the controller loads), your controller might be trying to access the variable before it's been assigned. The console.log($scope) shows it later because browser dev tools display live references—by the time you check the log, the value has been set.
  • Double-check how you're passing Rails' @resource data to Angular. If you're using ng-init, make sure it's attached to the same element (or a parent) of your controller, so the value lands in the correct scope. For example:
    <div ng-controller="TaskController" ng-init="taskEndTime = '<%= @resource.end_time.utc.iso8601 %>'">
      <!-- Your view content here -->
    </div>
    

Second: Fixing the negative remainingTime value

Negative time usually means one of two things:

  1. Backwards calculation: You might be subtracting the end time from the current time, instead of the other way around. It should be end_time - current_time to get positive time left (or negative if the task is done).
  2. Timezone mismatch: Rails often stores times in UTC, while Angular uses your local timezone by default. This can skew calculations. Always use UTC for both backend and frontend calculations to avoid this.

Step-by-Step Solution

Let's rewrite the controller logic to handle both issues cleanly:

1. Update the Rails-to-Angular data pass

Instead of passing a pre-calculated remaining time, pass the raw UTC end time from Rails. This lets Angular handle the calculation, avoiding timezone gaps.

2. Rewrite your Angular controller

angular.module('yourAppName').controller('TaskController', function($scope, $interval) {
  // Convert the Rails-provided UTC time to a Date object
  const taskEndUtc = new Date($scope.taskEndTime);

  // Function to calculate remaining time (in seconds)
  function updateRemainingTime() {
    // Get current time in UTC to match Rails' timezone
    const now = new Date();
    const nowUtc = new Date(Date.UTC(
      now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(),
      now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds()
    ));

    // Calculate difference in seconds (end time minus current time)
    $scope.remainingTime = Math.floor((taskEndUtc - nowUtc) / 1000);
  }

  // Initialize the value immediately
  updateRemainingTime();

  // Refresh every second for real-time updates
  $interval(updateRemainingTime, 1000);

  // Access the value safely with $watch (avoids undefined on load)
  $scope.$watch('remainingTime', (newVal) => {
    if (newVal !== undefined) {
      console.log('Current remaining time:', newVal);
      // Add your logic here once the value is available
    }
  });
});

3. Improve the view display

Hide negative time and show user-friendly text instead, plus a filter to format seconds into readable time:

<!-- Display formatted time if task is ongoing -->
<div ng-if="remainingTime > 0">
  Time remaining: {{ remainingTime | secondsToDhms }}
</div>
<!-- Show completion message if task is done -->
<div ng-if="remainingTime <= 0">
  Task X has been completed!
</div>

4. Add the time-formatting filter

angular.module('yourAppName').filter('secondsToDhms', () => {
  return (seconds) => {
    seconds = Number(seconds);
    const days = Math.floor(seconds / (3600 * 24));
    const hours = Math.floor((seconds % (3600 * 24)) / 3600);
    const minutes = Math.floor((seconds % 3600) / 60);
    const secs = Math.floor(seconds % 60);

    return [
      days > 0 ? `${days}d` : '',
      hours > 0 ? `${hours}h` : '',
      minutes > 0 ? `${minutes}m` : '',
      `${secs}s`
    ].filter(Boolean).join(' ');
  };
});

Quick Checks to Verify

  • Make sure Rails is outputting the end time in UTC ISO format (like 2024-05-20T14:30:00Z)—this is the most reliable format for Date objects in JS.
  • If you're still seeing undefined, check the browser's element inspector to confirm the ng-init value is being rendered correctly in the HTML.

内容的提问来源于stack exchange,提问作者José Antonio Camus Godoy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 04:18:00