область видимости angularjs в динамических элементах области видимости

0

У меня возникают проблемы с областями, созданными директивами, и с сохранением области динамических элементов обратно родителям.

Вот моя директива:

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>

вот мой newaction 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, и я попытался назвать вкладки с классами и найти их с вызовами документов, но это тоже не работает. У меня есть приложение, и я могу создавать группы, делеле и т.д., Триггеры (а не триггерные действия) и сцены, поэтому я понимаю основы контроллеров и областей. Но сохранение этих дочерних областей в главном триггере (то, что я предполагаю, было бы trigger.actions) меня насторожило. Может быть, есть лучший способ этого? Я знаю, что мой код может быть неэффективным, я пытаюсь получить базу, а затем очистить ее позже.

Спасибо.

ОБНОВИТЬ:

Итак, новая директива:

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

    }]);

Области действия для этих действий создаются, и когда я удаляю их, они регистрируются как объекты. Но действия не сохраняются в триггере. Я попытался создать actionObject, а затем ng-repeat = "action в actionsObject", но это не сработало. Я пытаюсь $ scope.trigger.actions = $ scope.actionsObject (безрезультатно) [моя мысль заключается в том, как я создал $ scope.trigger и объект $ scope.actionsObject, так это то, что они должны вести себя одинаково, если я вызываю действие в actionsObject Действие "против" в trigger.actions "..?]. Мое предположение заключается в том, что я добавляю шаблон newaction, который представляет собой действие, действие ng-repeat = "действие в trigger.actions", создает ли это привязку, когда я добавляю новый элемент в #actions, который он сохранил в trigger.actions scope? Наличие "scope: true" в директиве дает мне сцены и группы отлично (лучше понять наследование). Я должен отметить, что я создаю триггер (один) и добавляю несколько действий (какие группы и сцены являются частью ng-опций, поэтому мне нужны эти модели). Влияет ли множественное приложение на что-либо? Это моя последняя важная функция. Я ценю помощь!

  • 0
    Рад, что теперь у тебя получилось немного лучше. Однако после вашего обновления вы начинаете задавать второй вопрос, который, по-видимому, больше относится к пожарной базе, чем к угловым областям.
  • 0
    Я бы предложил установить расширение для разработчиков Angular для Chrome и использовать инспектор угловых областей, который появится в ваших инструментах разработчика.
Показать ещё 7 комментариев
Теги:
angularjs-scope
angularfire

2 ответа

0

В директиве по действиям используется область выделения, которая предназначена только для внутреннего использования.

Данные, которые вы хотите сохранить в массиве Actions-массивов (которые должны быть отправлены вместе с формой), должны перейти непосредственно в объект-объект, а не в область. Вы можете получить доступ к объекту action двумя способами:

Используйте дочернюю область (путем указания области: true вместо области: {}) Это позволяет вам получить доступ к переменным родительской области по наследованию:

  • $scope.action относится к текущему объекту действия (из ng-repeat)
  • $scope.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>

Надеюсь, что это поможет вам!

  • 0
    как в этом случае ActionObject связывается с $ scope.trigger.actions?
  • 0
    Это не. В случае изолированной области видимости (последний пример) переменные связаны в html-разметке. Как вы можете видеть в HTML, я использую the-action-object="action" . Это свяжет действие переменной области action ng-repeat с изолированной переменной области действия ActionObject. Обратите внимание, что я связываю элемент действия каждой итерации в ng-repeat. Это не весь массив, а текущий элемент. Таким образом, для первого действия $ scope.theActionObject будет связан с trigger.actions[0] а следующее действие будет связывать $ scope.theActionObject с trigger.actions[1] и так далее.
Показать ещё 3 комментария
0

где находятся ваши группы, сцены и объекты действий, определенные в $parent scope? Вам нужно будет определить их в вашем 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, а директивы действия будут использовать любую область, в которой они отображаются.

  • 0
    требует ли тот факт, что я создаю несколько элементов newaction, я использую изолированные области?
  • 0
    Это имеет значение только в том смысле, что если они совместно используют область видимости, изменения в $ scope в одном экземпляре происходят в других экземплярах. Если, например, директива newaction назначает $ scope вещи, которые должны быть специфичны только для этого экземпляра - тогда вам понадобится изолированная или прототипная унаследованная область. Если директива не присваивает что-то конкретное своему экземпляру в $ scope, тогда совместное использование scope - это нормально.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню