angularjs state cache false 阻止将 canvas 重新附加到 div

angularjs state cache false prevents re-attaching canvas to div

提问人:rolinger 提问时间:8/16/2023 更新时间:8/16/2023 访问量:7

问:

我发现了一个问题,即用户转到 PageA,用户单击打开模态的按钮,模态启动 rest API 调用,并使用从调用返回的信息创建 qrCode 并将 qrCode 作为附加到 ng-repeat 中创建的 DIV。模式将每 5 分钟刷新一次 qrCodes(基于时间戳)。在 PageA 上,用户可以打开/关闭模态而不会出现问题。一切似乎都很好。<canvas>

但是,当用户关闭模态并离开 PageA,然后返回 PageA 并再次打开模态时,将创建 qrCodes,但无法再附加到 DIV。当模式打开时,我可以看到 API 调用再次发生,我可以看到 API 调用中填充特定字段的其他信息,并且我能尽我所能地告诉 qrCode 函数正在创建图像,但它无法再次附加 DIV。每隔 5 分钟,我就会看到 API 再次调用,但新的 qrCode 图像永远不会再次附加。在源代码中,我可以看到应该附加到的正确 DIV - 因此 DIV 元素确实存在。<canvas>

经过数小时的故障排除,我看到我的状态控制器用于此页面。出于各种原因,我需要将其设置为 false。但是一时兴起,我设置了此页面并再次测试......这一次问题没有发生。我可以离开 PageA 并再次返回,qrCode 图像现在正确附加到 DIV 并每 5 分钟正确刷新一次(并验证它们是新的 qrCode 图像)。cache: falsecache: true

这是怎么回事?由于其他原因,我需要该页面,但是我可以使此qrCode问题正常工作的唯一方法是设置。我该如何解决这个问题?cache: falsecache: true

州:

  .state('tab.clubs', {
    cache: true,
    url: '/clubs',
    params: tabParams,
    views: {
      'tab-clubs': {
        templateUrl: 'templates/tab-clubs.html',
        controller: 'ClubCtrl'
      }
    }
  })
  .state('tab.club-detail', {
    cache: true,    // true: everything works, false: fails after routing away/back to club-detail
    url: '/clubs/:ceID',
    params: tabParams,
    views: {
      'tab-clubs': {
        templateUrl: 'templates/detail-clubs.html',  //this is the page with the modal on it
        controller: 'ClubDetailCtrl'
      }
    }
  })

控制器:

  $scope.ticketTimer ;
  $scope.ticketCSS = {} ;
  $scope.genQRCode = function() {
    $scope.refreshTickets = 1 ;
    clubService.getTickets($scope.club.cID,$scope.club.clID,$scope.club.ceID)
    .then(function(response) {
      $scope.refreshTickets = 0 ;
      if (response.success == true) {
        for (var x=0;x<response.tickets.length;x++) {
          var ticket = response.tickets[x] ;
            $scope.ticketCSS[ticket.ticketID] = {} ;
          // clear existing <canvas> from ticketDIV otherwise
          // the jQuery qrcode will just add more qrCodes to the DIV
          angular.element('#ticketID_'+ticket.ticketID).empty() ;
          if (ticket.scode == 0) {
            var ts = new Date(new Date().getTime() + 5 * 60000).toISOString().slice(0,19).replace("T"," ") ;
            $scope.ticketCSS[ticket.ticketID].status = "Open" ;
            $scope.ticketCSS[ticket.ticketID].stampTitle = "Refresh" ;
            $scope.ticketCSS[ticket.ticketID].stampText = ts ;
            $scope.ticketCSS[ticket.ticketID].img = "img/LiveScanner.gif" ;
            $scope.ticketCSS[ticket.ticketID].stampColor = "black" ;
          } else if (ticket.scode == 1) {
            var ts = new Date(ticket.sdate).toISOString().slice(0,19).replace("T"," ") ;
            $scope.ticketCSS[ticket.ticketID].status = "Scanned" ;
            $scope.ticketCSS[ticket.ticketID].stampTitle = "Scanned" ;
            $scope.ticketCSS[ticket.ticketID].stampText = ts ;
            $scope.ticketCSS[ticket.ticketID].stampColor = "green" ;
            $scope.ticketCSS[ticket.ticketID].img = "img/scanned1.png" ;
          } else if (ticket.scode == 2) {
            var ts = new Date(ticket.sdate).toISOString().slice(0,19).replace("T"," ") ;
            $scope.ticketCSS[ticket.ticketID].status = "Expired" ;
            $scope.ticketCSS[ticket.ticketID].stampTitle = "Expired" ;
            $scope.ticketCSS[ticket.ticketID].stampText = ts ;
            $scope.ticketCSS[ticket.ticketID].img = "img/expired.png" ;
            $scope.ticketCSS[ticket.ticketID].stampColor = "red" ;
          }
          if (ticket.ticketRefund == 0) {
            var refund = "No" ;
          } else {
            var refund = "Yes" ;
          }
          $scope.ticketCSS[ticket.ticketID].refunds = refund ;
          $scope.ticketCSS[ticket.ticketID].trans = "No" ;
          $scope.ticketCSS[ticket.ticketID].desc = ticket.ticketDesc ;
          
          // generate qrCode, this attaches a canvas to the specified element:
          // http://jeromeetienne.github.com/jquery-qrcode
          jQuery('#ticketID_'+ticket.ticketID).qrcode({width:150,height:150,text:ticket.liveCode}) ;
        }
      }
    }) ;

    // create timer to refresh tickets in 5 minutes
    $scope.ticketTimer = $timeout(function(){
      $scope.genQRCode() ;
    },300000) ;  // 5 minutes = 300000
  } ;
  
  
  $ionicModal.fromTemplateUrl('ticketModal.html', {
    scope: $scope,
    animation: 'slide-in-up',
    backdrop: 'static',
    backdropClickToClose:false,
    focusFirstInput: false 
  }).then(function(modal) {
    $scope.tixModal = modal;
  });
  
  
  $scope.openTicketModal = function(id) {
    
    // this interval is need to let ng-repeat in modal populate
    // before triggering the genQRCode() function - otherwise, the genQRCode()
    // will create the code and try to attach the `canvas` to the DIV
    // before the div is actually rendered - causing it to fail.
    //
    // this is needed because modal template/scripts are loaded into memory
    // when page/controller is loaded (even before modal is opened) causing genQRCode()
    // to initialize cause the same DIV not yet created issue above.  Not certain how to get
    // ng-repeat to call function on $last element AFTER the modal is opened. bizarre behavior.
    $scope.ticketInit = $interval(function() {
      var tid = $scope.club.tickets.length-1 ;
      var tik = $scope.club.tickets[tid] ;
      //if (angular.element(document.querySelector('#ticketID_'+tid))) {
      if (angular.element('#ticketID_'+tik.ticketID).length > 0) {
        $interval.cancel($scope.ticketInit) ;
        $scope.genQRCode() ;
      }
    },100) ;
    //$scope.tixModal.show() ;
    $rootScope.globalModalShow($scope.tixModal) ;
  } ;
  $scope.closeTicketModal = function(id) {
    if ($scope.ticketTimer !== null) {
      $timeout.cancel($scope.ticketTimer) ;
    }
    //$scope.tixModal.hide() ;    
    $rootScope.globalModalClose($scope.tixModal) ;
  }  ;

HTML格式:

  <div id="ticketContainer" ng-show="!refreshTickets" style="width:90%;margin-left:5%;margin-top:10px;overflow-y:hidden;">
    <div ng-repeat="ticket in club.tickets" id="ticketDiv_{{ticket.ticketID}}" style="position:relative;font-weight:bolder;min-width:100%;border:1px solid black;margin-bottom:20px;;" class="">
      <div id="ticketCount_{{ticket.ticketID}}" style="text-align:center;">{{$index+1}} of {{club.tickets.length}}</div>
      <div id="ticketScanner_{{ticket.ticketID}}" class="centerDivContents" style="position:absolute;margin-top:10px;">
        <img id="ticketImg_{{ticket.ticketID}}" ng-src="{{ticketCSS[ticket.ticketID].img}}">
      </div>
      <div id="ticketID_{{ticket.ticketID}}"class="centerDivContents" style="margin-top:20px;" ></div>
      <div style="margin:15px;">
        <div id="ticketName_{{ticket.ticketID}}" style="">Type: {{ticket.ticketName}}</div>
        <div id="ticketStatus_{{ticket.ticketID}}" style="">Status: <span style="color:{{ticketCSS[ticket.ticketID].stampColor}}">{{ticketCSS[ticket.ticketID].status}}</span></div>
        <div id="ticketStamp_{{ticket.ticketID}}" style="">{{ticketCSS[ticket.ticketID].stampTitle}}: <span style="color:{{ticketCSS[ticket.ticketID].stampColor}}">{{ticketCSS[ticket.ticketID].stampText}}</span></div>
        <div id="ticketRefund_{{ticket.ticketID}}" style="">Refunds: <span style="">{{ticketCSS[ticket.ticketID].refunds}}</span></div>
        <div id="ticketTrans_{{ticket.ticketID}}" style="">Transfers: <span style="">{{ticketCSS[ticket.ticketID].trans}}</span></div>
        <div id="ticketDesc_{{ticket.ticketID}}" style="white-space:break-spaces;">Desc: {{ticket.ticketDesc}}</div>
      </div>
    </div>
  </div>
jquery angularjs angular-ui-router modalviewcontroller

评论


答: 暂无答案