2016-08-24 38 views
1

我们正在使用Angularjs开发单页应用程序e-learning,并且我们需要跟踪某些组件是否“可完成”,如果它们完成。向应用程序添加存储状态的'角度方式'

不幸的是,我几乎可以肯定,我对Angularjs概念的理解是有缺陷的,所以在摆脱一些鞋角解决方案之前,我想知道实现这一点的'角度方式'是什么。

我已经将一个自定义属性指令'eng-completable'添加到组件的HTML模板(按钮单击时显示的弹出窗口)。我还可以添加一个(潜在虚假)NG-模型=“完成”变量声明......(下面第一行是有关的一个 - 其他都工作正常)

<div eng-completable ng-model="completed" class="hidden popup {{component.popup.type}}" id="{{component.popup.name}}" data-replaces="{{component.popup.replaces}}"> 
    <div ng-if="component.popup.type=='overlay'"> 
     <div class="float-right button close-button">X</div> 
    </div> 
    <p class="heading">{{component.popup.heading}}</p> 
    <div class="popup-content"> 
     <div ng-if="0" ng-repeat-start="(innerIndex, component) in component.popup.popup_components"></div> 
      <div ng-if="0" ng-repeat-start="(type, object) in component"></div> 
       <div ng-attr-id="{{'p' + pageId + '-s' + skey + '-c' + ckey + '-component-' + index + '-innerComponent-' + innerIndex}}" ng-switch="type"> 
        <div ng-switch-when="image" eng-image></div> 
        <div ng-switch-when="paragraph" eng-paragraph></div> 
       </div> 
      <div ng-if="0" ng-repeat-end></div> 
     <div ng-if="0" ng-repeat-end></div> 
    </div> 
</div> 

我已经添加了相应的指令到我们的app.js文件:

app.directive('engCompletable', function() { 
    return { 
     restrict: 'A', 
     link: function(scope, element, attrs) { 
      scope.completed = false; 
      console.log("completable attribute encountered and triggered: scope.completed = "+scope.completed); 
     } 
    } 
}); 

但那又怎样?如何从“全局”的角度访问已完成的变量?下一步似乎并不明显的事实表明我已经出错了。

在角度应用程序中存储和跟踪多个完成变量(在多个范围内?)的最佳方式是什么?

编辑

我想我可能需要包括更多的细节,真正显示我的问题:
假设我能在“completable”属性添加到每个CHI-completable指令的范围,当用户单击触发相应弹出组件的按钮组件(通过对DOM元素的id引用)时,如何引用弹出组件的角度范围来更改“completable”属性?

我明白,即使问题的框架可能有缺陷,但如果是这样,我想知道什么是“正确”的方式来做到这一点,在角度。

谢谢。

+0

你只想知道一件事情是完成还是多次? 你还想要触发多少东西? – RyanDawkins

+0

每个应用程序会有任何数量的补充。我们刚刚添加了第一个交互组件(一个弹出窗口和相应的按钮),但会有更多类型的可完成组件,并且它们可能会在应用程序中多次出现。 – moosefetcher

回答

1

订阅事件是在控制器之间共享数据的好方法。以下是与另一个控制器共享注释完成加载的示例,'controller1'将跟踪所有加载的注释。

正在等待,看看谁被加载

例控制器:

angular.module('app').controller('controller1', ['$scope', '$rootScope', function controller1($scope, $rootScope) { 

    var unsubscribe = $rootScope.$on('comment:loaded', commentLoaded);  

    $scope.$on('$destroy', function removeBindings() { 
     unsubscribe(); 
    }); 

    var commentIdsLoaded = {}; 
    function commentLoaded(event, comment) { 
     commentIdsLoaded[comment.id] = true; 
    } 

}); 

控制器被通知评论加载

angular.module('app').controller('controller2', ['$scope', '$rootScope', function controller2($scope, $rootScope) { 

    function commentFinishedLoading(comment) { 
     $rootScope.$emit('comment:loaded', comment); 
    } 

}); 

该解决方案使您无需将它们存储在$ rootScope只有管理评论将数据存储在需要它的模型中。如果更改页面,它也将防止存储有关这些数据的内存泄漏。

0

事件可能是在组件之间共享这种状态的最轻量级的方式,并且通常我会以开始来处理这类问题。

随着更多的组件间交互,事件会变得繁琐且容易出错。当有很多发射器和/或侦听器时,您需要确保正确的组件处理正确的消息。您也基本上都在中复制了每个相关组件中的状态,这使得容易出现不同步问题。

主要的替代方案是使用共享服务来管理共享状态,它允许没有状态重复。服务是单身人士,所以你可能不认为他们可以很好地管理多个独特的状态,但他们可以保存状态的地图(或数组),并且可以监视变化。

共享服务的方式可能类似于:

// Shared service 
angular.module('app').service('completables', function(){ 
    // A map of, perhaps { exerciseId : isCompleted } 
    var _states = {}; 
    // You could put getters and setters on here to be more explicit 
    return { 'states': _states } 
}); 

// Some high-level controller 
angular.module('app').controller('highLevel', ['completables', function(completables){ 
    $scope.completables = completables; 
    $scope.$watch('completeables.states', function(oldStates, newStates){ 
    // Do something whenever ANY states change 
    }); 
}); 

// Low-level directives 
app.directive('engCompletable', ['completables', function(completables){ 
    return { 
    scope: { exercise: '=' }, 
    link: function(scope, element, attrs) { 

     // Set initial (shared) state 
     completeables.state[scope.exercise.id] = false; 

     // Triggered by user interaction 
     scope.completeExercise = function(){ 
     completeables.state[scope.exercise.id] = true; 
     }; 

     // You could also watch for external changes to just this exercise 
     scope.completables = completeables; 
     scope.$watch('completables.' + [scope.exercise.id], function(oldState, newState){ 
     // Do something when changed externally 
     }); 
    } 
    } 
}]); 

共享服务带来了更多的观察家,所以记住这一点。但它保持了一个地方的状态 - 非常适合保持同步 - 并且感觉更强健一点。

相关问题