angularjs范围内的动态元素保存

时间:2016-08-01 19:26:20

标签: angularjs angularjs-scope angularfire

我在使用指令创建的作用域时遇到了麻烦,并将这些动态元素的作用域保存回父级。

这是我的指示:

app.directive('action', function() {
 return {
   restrict: "E",
   scope: {},
   templateUrl:'views/pages/projects/triggers/newaction.html',   
   controller: function($rootScope, $scope, $element) {
     $scope.groups = $scope.$parent.groups;  
     $scope.scenes = $scope.$parent.scenes;  
     $scope.actions = $scope.$parent.actions; 
     $scope.Delete = function(e) {
        //remove element and also destoy the scope that element
        $element.remove();
        $scope.$destroy();
      };
   }
 };
});

这是我的控制器:

.controller('NewTriggerCtrl', ['Auth', '$scope', 'toastr', '$state', '$stateParams', 'FBURL', '$filter', '$compile',
function(Auth, $scope, toastr, $state, $stateParams, FBURL, $filter, $compile) {

  var authData = Auth.$getAuth();
  var ref = new Firebase(FBURL + '/projects/' + authData.uid + '/' + $stateParams.projectid);
  // Submit operation

 var retriveActions = function() {
    // http://stackoverflow.com/questions/12649080/get-to-get-all-child-scopes-in-angularjs-given-the-parent-scope
    var theseactions = [];
    var ChildHeads = [$scope.$$childHead];
    var currentScope;
    while (ChildHeads.length) {
      currentScope = ChildHeads.shift();
      while (currentScope) {
         /* theseactions.push({
            type: currentScope.type,
            data: currentScope.data,
            data2: currentScope.data2
          }); */
          console.log("currentscope.type = " + currentScope.type);
        };
        currentScope = currentScope.$$nextSibling;
    }
    //return theseactions;
  };

  var retrieveactions2 = function() {
    var theseactions = [];
    var newevent = null;
    var newdata = null;
    var newdata2 = null;
    console.log("in retrieve actions");
    angular.forEach(angular.element(document.getElementsByClassName("newaction")), function(element){
        console.log("iterating");
        newevent = $(this).find('.newactionevent').value;
        newdata = $(this).find('.newactiondata').value;
        newdata2 = $(this).find('.newactiondata2').value;
        theseactions.push({
            event: newevent,
            data: newdata,
            data2: newdata2
        });
    });
    return theseactions;
  }


  $scope.ok = function(actions) {
    //console.log(retriveActions(actions));
    //retriveActions(actions);
    //console.log("$scope.trigger.actions = " + $scope.trigger.actions);
    //console.log("actions = " + actions);
    console.log(retrieveactions2());
    $scope.triggers.$add($scope.trigger).then(function (triggerRef) {
      ref.child('triggers').child(triggerRef.key())
        .update({created_at: Firebase.ServerValue.TIMESTAMP});
      toastr.success('Trigger Added!', 'Trigger has been created');
      $state.go('app.projects.edit', {projectid : $stateParams.projectid}, {reload: true});
    });
  };
  $scope.newaction = function() {
      var divElement = angular.element(document.querySelector('#actions'));
      var appendHtml = $compile('<action></action>')($scope);
      divElement.append(appendHtml);
  };
  $scope.cancel = function() {
      $state.go('app.projects.edit', {projectid : $stateParams.projectid}, {reload: true});
    };
  /////////////////////// *Submit operation

}])

这是我的新触发器html:

<div class="page page-newtrigger" ng-controller="NewTriggerCtrl">

  <!-- row -->
  <div class="row">


    <div class="col-md-12">

      <!-- tile -->
      <section class="tile tile-simple">


        <!-- tile body -->
        <div class="tile-body">

            <form name="form" class="form-horizontal form-validation" role="form" novalidate>
                  <div class="form-group mt-12" style="margin-top: 15px;">
                    <label for="name" class="col-sm-1 control-label">Name <span class="text-danger" style="font-size: 15px;">*</span></label>
                    <div class="col-sm-1">
                      <input type="text" name="name" class="form-control" id="name" placeholder="Trigger name..." ng-model="trigger.name" required>
                    </div>

                        <div class="btn-group col-sm-2">
                            <label class="btn btn-green" ng-model="trigger.type" uib-btn-radio="'astro'">Astro</label>
                            <label class="btn btn-green" ng-model="trigger.type" uib-btn-radio="'time'">Real-Time</label>
                            <label class="btn btn-green" ng-model="trigger.type" uib-btn-radio="'input'">Input</label>
                        </div>


                    <div class="animate-switch-container" ng-switch on="trigger.type">

                        <div class="animate-switch" ng-switch-when="astro">
                            <div class="btn-group col-sm-2">
                              <label class="btn btn-green" ng-model="trigger.event" uib-btn-radio="'sunrise'">Sunrise</label>
                              <label class="btn btn-green" ng-model="trigger.event" uib-btn-radio="'sunset'">Sunset</label>
                            </div>
                            <div class="col-sm-1">
                                <input type="text" name="offset" class="form-control" id="offset" placeholder="Offset (+/- minutes)" ng-model="trigger.option">
                            </div>
                        </div>

                        <div class="animate-switch" ng-switch-when="time">
                            <div class="btn-group col-sm-2">
                              <label class="btn btn-green" ng-model="trigger.event" uib-btn-radio="'repeat'">Repeat</label>
                              <label class="btn btn-green" ng-model="trigger.event" uib-btn-radio="'once'">Once</label>
                            </div>

                            <div class="animate-switch-container" ng-switch on="trigger.event">
                                <div class="animate-switch" ng-switch-when="repeat">
                                    <div class="col-sm-3 btn-group">
                                      <label class="btn btn-cyan" ng-model="trigger.option.mon" uib-btn-checkbox>Mon</label>
                                      <label class="btn btn-cyan" ng-model="trigger.option.tue" uib-btn-checkbox>Tue</label>
                                      <label class="btn btn-cyan" ng-model="trigger.option.wed" uib-btn-checkbox>Wed</label>
                                      <label class="btn btn-cyan" ng-model="trigger.option.thu" uib-btn-checkbox>Thur</label>
                                      <label class="btn btn-cyan" ng-model="trigger.option.fri" uib-btn-checkbox>Fri</label>
                                      <label class="btn btn-cyan" ng-model="trigger.option.sat" uib-btn-checkbox>Sat</label>
                                      <label class="btn btn-cyan" ng-model="trigger.option.sun" uib-btn-checkbox>Sun</label>  
                                    </div>
                                    <div class="col-sm-1">
                                        <input type="text" name="time" class="form-control" id="time" placeholder="Time (HH:mm:ss)" ng-model="trigger.data">
                                    </div>
                                </div>
                                <div class="animate-switch" ng-switch-when="once">
                                    <div class="col-sm-2" >
                                        <p class="input-group" ng-controller="DatepickerDemoCtrl">
                                          <input type="text" class="form-control" uib-datepicker-popup="{{format}}" ng-model="trigger.option" is-open="opened" min-date="minDate" datepicker-options="dateOptions" date-disabled="disabled(date, mode)" ng-required="true" close-text="Close" />
                                          <span class="input-group-btn">
                                            <button type="button" class="btn btn-default" ng-click="open($event)"><i class="fa fa-calendar"></i></button>
                                          </span>
                                        </p>
                                    </div>
                                    <div class="col-sm-1">
                                        <input type="text" name="time" class="form-control" id="time" placeholder="Time (HH:mm:ss)" ng-model="trigger.data">
                                    </div>
                                </div>
                            </div>
                        </div>

                        <div class="animate-switch" ng-switch-when="input">
                            <div class="col-sm-1">
                                <select ng-init="1" ng-model="trigger.option" class="form-control mb-10">
                                    <option value="1">1</option>
                                    <option value="2">2</option>
                                    <option value="3">3</option>
                                    <option value="4">4</option>
                                    <option value="5">5</option>
                                    <option value="6">6</option>
                                    <option value="7">7</option>
                                    <option value="8">8</option>
                                </select>
                            </div>
                            <div class="col-sm-2">
                                <div class="btn-group">
                                  <label class="btn btn-green" ng-model="trigger.event" uib-btn-radio="'high'">Goes high</label>
                                  <label class="btn btn-green" ng-model="trigger.event" uib-btn-radio="'low'">Goes low</label>
                                </div>
                            </div>
                        </div>
                    </div>

                    <button class="btn btn-success b-0 pull-right" style="margin-right: 30px;" ng-click="newaction()"><i class="fa fa-plus mr-5"></i>New Action</button>

                  </div>
                  <div id="actions">
                  <action ng-repeat="action in trigger.actions"></action>
                  </div>

                  <div class="form-footer">
                    <button class="btn btn-success b-0 pull-right" ng-click="ok(trigger)" ng-disabled="form.$invalid">Submit</button>
                    <button class="btn btn-lightred btn-ef btn-ef-4 btn-ef-4c" ng-click="cancel()"><i class="fa fa-arrow-left"></i> Cancel</button>
                  </div>
            </form>

        </div>
        <!-- /tile body -->


      </section>
      <!-- /tile -->

    </div>

  </div>
  <!-- /row -->

</div>

这是我的新动作html:

    <!-- row -->
  <div class="newaction row">
    <div class="col-md-10 col-sm-offset-2">
            <form name="form" class="form-horizontal form-validation" role="form" novalidate>
                  <div class="form-group mt-12" style="margin-top: 15px;">

                  <div class="col-sm-1"><button ng-click="Delete($event)" class="btn btn-danger"><i class="glyphicon glyphicon-trash"></i></button></div>

                        <div class="btn-group col-sm-2">
                            <select ng-init="1" ng-model="action.type" class="newactiontype form-control mb-10">
                                <option value="transition-scene">Transition Scene</option>
                                <option value="set-group-intensity">Set Group Intensity</option>
                                <option value="inject-trigger">Inject Trigger</option>
                                <option value="color-change">Color Change</option>
                            </select>
                        </div>


                    <div ng-if="action.type=='transition-scene'">
                        <div class="col-sm-3">
                          <select chosen="" class="newactionevent form-control mb-10" ng-options="scene.name for scene in scenes track by scene.name" ng-model="action.scene"></select>
                        </div>
                        <div class="col-sm-1">
                            <input type="text" name="fadetime" class="newactiondata form-control" id="fadetime" placeholder="Fade Time (seconds)" ng-model="action.fadetime">
                        </div>
                    </div>

                    <div ng-if="action.type=='set-group-intensity'">
                        <div class="col-sm-3">
                          <select multiple chosen="" class="newactionevent form-control mb-10" ng-options="group.name for group in groups track by group.name | filter: {type : 'white'}" ng-model="$parent.action.group"></select>
                        </div>
                        <div class="col-sm-1">
                            <input type="text" name="intensity" class="newactiondata form-control" id="intensity" placeholder="Intensity(%)" ng-model="action.intensity">
                        </div>
                        <div class="col-sm-1">
                            <input type="text" name="fadetime" class="newactiondata2 form-control" id="fadetime" placeholder="Fade Time (sec)" ng-model="action.fadetime">
                        </div>
                    </div>

                    <div ng-if="action.type=='inject-trigger'">
                        <div class="col-sm-2">
                          <input type="text" name="triggernumber" class="newactiondata form-control" id="triggernumber" placeholder="Trigger number..." ng-model="action.data">
                        </div>
                    </div>

                    <div ng-if="action.type=='color-change'">
                        <div class="col-sm-3">
                          <select multiple chosen="" class="newactionevent form-control mb-10" ng-options="group.name for group in groups track by group.name| filter:group.type!='white'" ng-model="action.group"></select>
                        </div>
                        <div class="col-sm-1">
                            <input colorpicker="rgb" ng-model="action.data" type="text" class="newactiondata form-control w-md mb-10">
                        </div>
                        <div class="col-sm-1">
                            <input type="text" name="fadetime" class="newactiondata2 form-control" id="fadetime" placeholder="Fade Time (sec)" ng-model="action.fadetime">
                        </div>
                    </div>
                  </div>
            </form>


    </div>

  </div>
  <!-- /row -->

我有多次尝试,你可以在NewTriggerCtrl中看到两个不同的函数。第一个是获取所有子范围并迭代,但是当我调用它时,它会锁定浏览器超过250,000个日志。也许我传的错误范围?

我对Angular相对较新,并且在JQuery方面有一些经验,我试图用类命名输入并使用文档调用查找它们,但这也不起作用。我有一个运行的应用程序,我可以创建,检测等组,触发器(不是触发器操作)和场景,所以我理解控制器和范围的基础知识。但是将这些子范围保存到主触发器(我认为是触发器。)让我很难过。也许还有更好的方法吗?我知道我的代码可能效率不高,我试图获得一个基础然后再清理。

谢谢。

更新:

好的新指令:

app.directive('action', function() {
 return {
   restrict: "E",
   scope: true,
   templateUrl:'views/pages/projects/triggers/newaction.html',   
   controller: function($rootScope, $scope, $element) {
     $scope.Delete = function(e) {
         console.log("$scope.action = " + $scope.action);
        //remove element and also destoy the scope that element
        $element.remove();
        $scope.$destroy();
      };
   }
 };
});

和整个触发控制器:

'use strict';

app

  .controller('TriggersCtrl', ['Auth', '$scope', '$state', '$stateParams', '$firebaseArray', '$firebaseObject', 'FBURL',
    function(Auth, $scope, $state, $stateParams, $firebaseArray, $firebaseObject, FBURL) {

      // General database variable
      var authData = Auth.$getAuth();
      var ref = new Firebase(FBURL + '/projects/' + authData.uid + '/' + $stateParams.projectid);


      $scope.triggers = $firebaseArray(ref.child('triggers'));
      $scope.groups = $firebaseArray(ref.child('groups'));
      $scope.scenes = $firebaseArray(ref.child('scenes'));
      $scope.triggersObject = $firebaseObject(ref.child('triggers'));
      //////////////////////////// *General database variable

      // get the model
      if($stateParams.triggerid) {
        var id = $stateParams.triggerid;
        $scope.trigger = $firebaseObject(ref.child('triggers').child(id));
        $scope.actionsObject = $firebaseObject(ref.child('triggers').child(id).child('actions'));
      } else {
        $scope.trigger = {};
        $scope.actionsObject = {};
      }
    }])

  .controller('NewTriggerCtrl', ['Auth', '$scope', 'toastr', '$state', '$stateParams', 'FBURL', '$filter', '$compile', '$firebaseArray',
    function(Auth, $scope, toastr, $state, $stateParams, FBURL, $filter, $compile, $firebaseArray) {

      var authData = Auth.$getAuth();
      var ref = new Firebase(FBURL + '/projects/' + authData.uid + '/' + $stateParams.projectid);
      // Submit operation


    $scope.ok = function() {
        console.log("$scope.actions = " + $scope.actions);
        console.log("$scope.trigger.actions = " + $scope.trigger.actions);
        $scope.triggers.$add($scope.trigger).then(function (triggerRef) {
          ref.child('triggers').child(triggerRef.key())
            .update({created_at: Firebase.ServerValue.TIMESTAMP});
          toastr.success('Trigger Added!', 'Trigger has been created');
          $state.go('app.projects.edit', {projectid : $stateParams.projectid}, {reload: true});
        });
      };
      $scope.newaction = function() {
          var divElement = angular.element(document.querySelector('#actions'));
          var appendHtml = $compile('<action></action>')($scope);
          divElement.append(appendHtml);
      };
      $scope.cancel = function() {
          $state.go('app.projects.edit', {projectid : $stateParams.projectid}, {reload: true});
        };
      /////////////////////// *Submit operation

    }]);

创建操作的范围,当我删除时,它们被记录为对象。但是这些动作并没有保存到触发器中。我尝试创建一个actionsObject然后ng-repeat =“actionsObject中的动作”但是没有用。我尝试$ scope.trigger.actions = $ scope.actionsObject(无济于事)[我的想法是如何创建$ scope.trigger和$ scope.actionsObject,如果我在actionsObject中调用“action”,它们的行为应该相同trigger.actions中的“vs”动作“..?”。我的假设是我追加newaction模板,它的作用域是动作,ng-repeat =“action in actions.actions”部分,当我将新元素添加到保存到其中的#actions时,这是否会创建绑定trigger.actions范围?在指令中使用“scope:true”可以完美地给出场景和组(更好地理解继承)。我应该注意到我创建了一个触发器(单个)并添加了多个动作(哪些组和场景是ng-options的一部分,这就是我需要这些模型的原因)。多个附加是否会影响任何内容?这是我最后一个重要的功能。我很感激帮助!

2 个答案:

答案 0 :(得分:0)

您的action指令使用隔离范围,仅供指令内部使用。

要保存在Actions-array中的数据(与表单一起提交)应该直接进入action-object而不是作用域。 您可以通过两种方式访问​​action-object:

使用子范围(通过指定范围:true而不是范围:{}) 这允许您通过继承访问父的范围变量:

  • $scope.action引用当前操作对象(来自ng-repeat)
  • $scope.groups是指父范围
  • 中的groups数组

这意味着您可以将数据分配给$scope.action.something,它会立即影响操作对象。这就是角度之美:直接操纵数据,跳过繁琐的“循环通过一切来获取价值”。

您还可以使用隔离范围(使用scope: {}语法)。使用隔离范围时,需要明确指定要使用的变量。

{
    ...
    scope: {
        theActionObject: '=',
        groupList: '=',
        sceneList: '='
    }
    ...
}

然后可以在指令的链接或控制器函数中将其作为$ scope.theActionObject引用。

$scope.theActionObject.something = 'test';

// Access the groups array
alert($scope.groupList.length);

要将它们绑定在一起,您需要在HTML中指定引用:

              <div id="actions">
                  <action ng-repeat="action in trigger.actions" 
                          the-action-object="action" 
                          group-list="groups" 
                          scene-list="scenes"></action>
              </div>

希望这会对你有帮助!

答案 1 :(得分:0)

$parent范围内定义的组,场景和操作对象在哪里?您需要在NewTriggerCtrl

中定义它们
$scope.groups = [];
$scope.scenes = [];
$scope.actions = [];

由于您正在隔离范围,因此通常会通过以下属性绑定它们:

scope: {groups: '=', scenes: '=', actions: '=' }

<action ng-repeat="action in trigger.actions" groups="groups" scenes="scenes" actions="actions"></action>

隔离范围的替代方法是使用scope: true

的原型继承范围

无论哪种方式,绑定$scope.foo = $scope.$parent.foo;似乎都是不必要的。

如果您确实需要每个操作指令的新范围,那么这两种方法都适用。如果不这样做,则可以将scope属性保留在action指令定义之外,action指令将使用它们呈现的任何范围。