I am having quite the trouble with scopes created by directives, and saving these dynamic elements' scope back to the parent.
Here is my directive:
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();
};
}
};
});
here is my controller:
.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
}])
here is my new trigger 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>
here is my 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 -->
I have multiple attempts at this, as you can see with the two different functions in NewTriggerCtrl. The first was to get all the child scopes and iterate through, however when I call this it locks the browser up with over 250,000 logs. So maybe I am passing the wrong scope?
I am relatively new to Angular, and have some experience in JQuery, and I attempted to name the inputs with classes and finding them with document calls, but that is not working either. I have an app running and I can create, detele, etc. groups, triggers (not the trigger actions), and scenes, So I understand the basics of controllers and scopes. But saving these child scopes to the main trigger (what I assume would be trigger.actions) has stumped me. Maybe there is a better way to this? I know my code may not be efficient, I am attempting to get a base then clean up later.
Thank you.
UPDATE:
Ok so new directive:
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();
};
}
};
});
and entire trigger controller:
'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
}]);
The scopes for the actions are created, and when i delete they are logged as an object. But the actions are not saved into trigger. I tried creating an actionsObject and then ng-repeat="action in actionsObject" but that didnt work. I try $scope.trigger.actions = $scope.actionsObject (to no avail) [my thought is how I created the $scope.trigger and the $scope.actionsObject is that they should behave the same if I call "action in actionsObject" vs "action in trigger.actions"..?]. My assumption is that I append the newaction template, which it's scope is action, the ng-repeat="action in trigger.actions" part, does this create the bind for when I add the new element to #actions that it saved to the trigger.actions scope? Having "scope: true" in the directive gives me the scenes and groups perfectly (understand the inheritance a little better). I should note that I create a trigger (a single one) and add multiple actions (which groups and scenes are part of the ng-options which is why i needed those models). Does the multiple appends affect anything? This is my last major feature to work out. I appreciate the help!