angularjs scope within scope dynamic elements saving - angularjs

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!

Your action directive use an isolate scope, and that is for internal use by the directive only.
The data you want to save in your Actions-array (to be submitted with the form) should go directly into the action-object and not on the scope.
You can access the action-object in two ways:
Use a child scope (by specifying scope: true instead of scope: {})
This allows you to access the parent's scope variables by inheritance:
$scope.action refers to the current action object (from ng-repeat)
$scope.groups refers to the groups array from the parent scope
This means you can assign data to $scope.action.something and it will affect the action object immediately. This is the beauty of angular: Manipulate the data directly, and skip the tedious "loop through everything to get the values".
You can also use an isolate scope (using scope: {} syntax). When using an isolate scope you need to specify explicitly the variables you want to use.
{
...
scope: {
theActionObject: '=',
groupList: '=',
sceneList: '='
}
...
}
This can then be referenced in you directive's link or controller function as $scope.theActionObject.
$scope.theActionObject.something = 'test';
// Access the groups array
alert($scope.groupList.length);
And to tie it together you need to specify the references in the HTML:
<div id="actions">
<action ng-repeat="action in trigger.actions"
the-action-object="action"
group-list="groups"
scene-list="scenes"></action>
</div>
Hope this will help you!

where are your groups, scenes and actions objects defined on the $parent scope? You would need to define them in your NewTriggerCtrl
$scope.groups = [];
$scope.scenes = [];
$scope.actions = [];
Since you are isolating scope, you would normally bind them through attributes like:
scope: {groups: '=', scenes: '=', actions: '=' }
and
<action ng-repeat="action in trigger.actions" groups="groups" scenes="scenes" actions="actions"></action>
An alternative to isolate scope would be to use a prototypical inherited scope with scope: true
Either way, binding $scope.foo = $scope.$parent.foo; seems unnecessary.
Those two methods are for if you actually need new scopes for each action directive. If you don't, then you can just leave the scope property out of your action directive definition and the action directives will use whatever scope they are rendered in.

Related

ng-model value not passed to the controller function

I am using ng-model to pass the form value to a controller function. But it is not passing correct values of the check boxes. Here is my plunker. Please help me out with this.
https://plnkr.co/edit/3gOuQwzt3SMNbAXplq0x?p=preview
My template is:
<div class="tab-pane fade " ng-repeat="(key, value) in all_user_wl_data" id="{{key}}" ng-class='{"in active":$first}'>
<div class="form-group">
<div class="row">
<div class="col-sm-6 col-md-6 col-lg-6" ng-repeat="(key1, value1) in value.wl_dict">
<div class="checkbox checkbox-success">
<input id="{{key1}}" type="checkbox" name="valueis" class="form-control" ng-model="formData[key1]">
<label for="{{key1}}">
{{value1}}
</label>
</div>
</div>
</div>
</div>
<div class="form-group">
<div class="row"><div class="col-lg-3 col-md-3 col-sm-3"> <label class="control-label">Group Name </label></div>
<div class="col-md-6 col-sm-6 col-lg-6"> <input type="text" name="regular" class="form-control" ng-model="formData.key2"></div></div><br>
<button type="button" class="btn btn-success" data-original-title="" title="" ng-click="createGroup(formData)">Save changes</button>
</div>
Here when I print console.log(formData), it prints only the value of text box and doesn't prints checkbox value.
try this. in controller define $scope.formData = [];
You didn't initiate $scope for checkbox ng-model "formData" ..
So if you initiate model into controller like this , $scope.formData = []
It will append true value in your formData like this,
[2221: true, 8233: true]
As everyone suggested.
Set $scope.formData in controller
Working plnkr
use
$scope.formData = {}
in your controller
https://plnkr.co/edit/53YVnVyOQzqxHQIPshkq?p=preview
I changed your script to below and it works
angular.module('formExample', []) .controller('ExampleController', ['$scope', '$http', function($scope, $http) {
$scope.formData = {};
$http.get('test.json')
.success(function(data) {
$scope.all_user_wl_data = data;
angular.forEach(data, function(areadata) {
$scope.usersubscribedwl = data;
console.log(data);
})
})
$scope.createGroup = function() {
console.log($scope.formData);
}
}
try this
<input id="{{key1}}" type="checkbox" name="valueis" class="form-control" ng-model="formData.key1[value1]">
and in controller
$scope.formData=[];
https://plnkr.co/

Bootstrap modal form elements unfocussable (on mobile/mobile emulation)

From the repo: https://github.com/jmsherry/kitchenapp
Live at: https://kitchenapp2.herokuapp.com
If you click the 'contact us' link in the bottom right corner of the screen a modal appears. The modal is coded like:
<div class="modal-container">
<button type="button" class="close" aria-label="Close" ng-click="$close(null)">
<span aria-hidden="true">×</span>
</button>
<div class="content">
<h1>Contact Us</h1>
<div class="contact-form">
<form ng-submit="vm.sendMessage(this)" novalidate name="contactForm">
<div class="form-group" ng-if="vm.user && vm.user.email">
<p class="faux-label">From: <span class="faux-value">{{vm.user.email}}</span></p>
</div>
<div class="form-group" ng-class="{ 'has-error' : contactForm.from.$invalid && !contactForm.from.$pristine }" ng-if="!vm.user || !vm.user.email">
<label for="subject">From</label>
<input type="email" name="from" id="from" class="form-control" placeholder="From" ng-model="vm.user.email" ng-maxlength="30" ng-required="true" autofocus>
<ul ng-if="contactForm.from.$invalid && !contactForm.from.$pristine" ng-messages="contactForm.from.$error" class="help-block list-unstyled">
<li ng-message="maxlength">The subject must be less than 30 characters.</li>
<li ng-message="email">Not a valid email. Please check carefully and try again...</li>
</ul>
</div>
<div class="form-group" ng-class="{ 'has-error' : contactForm.subject.$invalid && !contactForm.subject.$pristine }">
<label for="subject">Subject</label>
<input type="text" name="subject" id="subject" class="form-control" placeholder="Subject" ng-model="vm.email.subject" ng-maxlength="30">
<ul ng-if="contactForm.subject.$invalid && !contactForm.subject.$pristine" ng-messages="contactForm.subject.$error" class="help-block list-unstyled">
<li ng-message="maxlength">The subject must be less than 30 characters.</li>
</ul>
</div>
<div class="form-group" ng-class="{ 'has-error' : contactForm.message.$invalid && !contactForm.message.$pristine }">
<label for="message">Message</label>
<textarea name="message" id="message" class="form-control" placeholder="Message..." ng-model="vm.email.body" ng-required="true" ng-minlength="10" ng-maxlength="500"></textarea>
<ul ng-if="contactForm.message.$invalid && !contactForm.message.$pristine" ng-messages="contactForm.message.$error" class="help-block list-unstyled">
<li ng-message="required">A description is required.</li>
<li ng-message="minlength">The name must be longer than 10 characters.</li>
<li ng-message="maxlength">The name must be less than 500 characters.</li>
</ul>
</div>
<!-- <div class="form-group"> -->
<div class="checkbox">
<label for="cc_self">
<input type="checkbox" id="cc_self" name="cc_self" ng-model="vm.email.cc_self">Send a copy to my email.
</label>
</div>
<!-- </div> -->
<div class="form-group">
<div class="pull-right">
<button type="button" class="btn btn-default" ng-click="$close(null)">Cancel</button>
<button type="submit" class="btn btn-primary" ng-disabled="contactForm.$invalid">Send</button>
</div>
</div>
</form>
</div>
</div>
</div>
Controller looks like:
angular.module('kitchenapp.directives')
.controller('KaFooterCtrl', ['$scope', '$q', '$log', '$modal', 'Email', 'Auth', 'toastr', function ($scope, $q, $log, $modal, Email, Auth, toastr) {
var vm = this,
$user;
function contact(day) {
$log.log('contact fn', arguments);
$modal.open({
templateUrl: '/views/modals/contact-modal.html',
controller: function modalController($modalInstance, $scope) {
$scope.vm = this;
$scope.vm.email = vm.email;
$scope.vm.user = vm.user;
$scope.vm.sendMessage = function () {
$modalInstance.close();
$q.when(vm.user, function (user) {
var $emailSent = Email.sendEmail(vm.email, vm.user);
$q.when($emailSent, function (res) {
toastr.success('Email sent! Thank you for your interest...');
}, function () {
toastr.error('We\'re sorry your email hasn\'t been sent, please try again later...');
});
});
event.preventDefault();
event.stopPropagation();
};
},
contollerAs: 'vm'
});
}
vm.year = new Date().getFullYear();
vm.email = {};
$user = Auth.getUser();
$q.when($user, function (user) {
vm.user = user;
});
vm.contact = contact;
vm.name = 'KaFooterCtrl';
}])
.directive('kaFooter', function () {
return {
restrict: 'E',
replace: true,
templateUrl: 'directives/footer/footer.html',
scope: {
companyName: '#',
companyEmail: '#'
},
controller: 'KaFooterCtrl as vm',
bindToController: true
};
});
}());
For some reason the first element focusses once, but any further interaction and the elements are not focussable by touch or mouse. Any clues why?
Thanks
So, it transpires that this is a problem when ng-touch is used. ng-touch auto-blurs the fields (https://github.com/angular/angular.js/pull/11212). A fix is on the way, but for now the user #jdhiro suggests using a directive to stop propagation of the touchend event outside of your modal. See https://github.com/angular-ui/bootstrap/issues/2017#issuecomment-39515923 for more

angularjs: Form entry problems

I have this dynamic form which entries I would like to save. The problem is that the saved entry is like this [{"name":"Noora","":{"Gender":"Woman","Address":"filler address"}}] I'm curios why the app saves the info after name like a nameless list. Name is hardcoded input and the other two (Gender and Address) can be dynamically added when using the program.
Here is the form entry html part:
<form>
<h2>Sign in:</h2>
<div class="form-group">
<label for="eventInput">Name</label>
<input style="width: 200px;" type="text" class="form-control" id="eventInput" data-ng-model="newEntry.name">
</div>
<div data-ng-repeat="field in event.fields">
<div class="form-group">
<label for="{{$index + 1}}">{{field.name}}</label>
<input style="width: 200px;" type="text" class="form-control" id="{{$index + 1}}" data-ng-model="newEntry.[field.name]">
</div>
</div>
<span>{{entries}}</span>
<div class='wrapper text-center'>
<div class="form-group">
<div class="col-lg-4 col-lg-offset-4">
<button style="width: 100px;" data-ng-click="addEntry()" class="btn btn-primary">Enroll</button>
<p></p>
<button style="width: 100px;" data-ng-click="back()" class="btn btn-primary">Back</button>
</div>
</div>
</div>
</form>
and here is the controller:
App.controller('aboutController', function($scope, $location, $routeParams, eventService) {
$scope.event = eventService.getCustomers()[$routeParams.id];
$scope.back = function() {
$location.path('/');
};
$scope.addEntry = function() {
$location.path('/');
$scope.event.entries.push($scope.newEntry);
};
});
I would like to either be able to name the child list or just record the entries into a continuous list. Any idea how would it be possible?
Br,
Norri

One model not accessible, one is

I have two tiny projects, both use essentially the same setup, one returns a model value one returns the model value as undefined. At this point I am lost as to why these two examples are behaving differently. I checked the failing example, and the model correctly populates
Successful Behavior
Partial
<div class="row">
<div class="col-md-4 .col-md-offset-4 content-pane no-margin">
<h4>Input Your Inquiry</h4>
<form ng-submit="submit(invoice)">
<div class="control-group">
<div class="controls">
<div class="input-prepend">
<span class="add-on">Invoice Number</span>
<input id="who" type="text" class="input-xlarge" ng-model="invoice.number">
</div>
</div>
</div>
<div class="control-group">
<div class="controls">
<div class="input-prepend">
<span class="add-on">PO Number</span>
<input id="who" type="text" class="input-xlarge" ng-model="invoice.po">
</div>
</div>
</div>
<input type="submit">
</form>
</div>
<div ng-if="status" class="col-md-4 .col-md-offset-4 content-pane no-margin">
<h4>Invoice Status</h4>
<div>{{status}}</div>
</div>
</div>
App.js
app.config(function($routeProvider){
$routeProvider
.when('/',
{
templateUrl: 'app/partials/inquiry-input-form.html',
controller: 'MainCtrl'
})
.otherwise(
{
templateUrl: 'app/partials/404.html'
})
});
app.controller('MainCtrl', function($scope,formsResults) {
$scope.submit = function() {
var invoiceNum = $scope.invoice.number;
var po = $scope.invoice.po;
formsResults.getInvoiceStatus(po,invoiceNum).success(function(data) {
var status = data.records;
if (angular.isUndefined(status)) {
$scope.status = 'Pending Reciept or Entry';
} else {
$scope.status = status[0].field_124208[0];
}
});
};
});
app.factory('formsResults', function($http) {............
Returning Model as undefined in controller
Partial
<tabset>
<tab active=workspace.active>
<tab-heading>
Search All Fields
</tab-heading>
<div>
<br /><br />
<form class="form-horizontal" ng-submit="submitAll(searches)">
<div class="form-group">
<div class="col-md-4">
<input id="textinput" name="textinput" type="text" class="form-control input-md" ng-model="searches.term">
<span class="help-block">Enter the term you wish to search on.</span>
{{searches.term}}
</div>
</div>
<!-- Button -->
<div class="form-group">
<div class="col-md-4">
<button id="singlebutton" name="singlebutton" class="btn btn-primary" type="submit">Search</button>
</div>
</div>
</form>
</div>
</tab>
<tab>
<tab-heading>
Search By Field
</tab-heading>
<div>
<br /><br />
<form class="form-horizontal" ng-submit="submitSpecific(search)">
<div class="form-group">
<div class="col-md-4">
<select id="selectbasic" name="selectbasic" class="form-control">
<option value="4">Country</option>
</select>
<span class="help-block">Enter the field you wish to search on.</span>
</div>
</div>
<!-- Text input-->
<div class="form-group">
<div class="col-md-4">
<input id="textinput" name="textinput" type="text" class="form-control input-md">
<span class="help-block">Enter the term you wish to search on.</span>
</div>
</div>
<div class="form-group">
<div class="col-md-4">
<button id="singlebutton" name="singlebutton" class="btn btn-primary" type="submit">Search</button>
</div>
</div>
</form>
</div>
</tab>
</tabset>
App.js
var app = angular.module ('app',['ngRoute','ngSanitize','ui.bootstrap','dialogs.controllers','dialogs']);
app.config(function($routeProvider){
//http://docs.angularjs.org/tutorial/step_07
$routeProvider
.when('/',
{
templateUrl: 'app/partials/home_tpl.html',
controller: 'HomeCtrl'
})
.when('/search',
{
templateUrl: 'app/partials/search-form.html',
controller: 'SearchCtrl'
})
.when('/add-sop',
{
templateUrl: 'app/partials/support-process.html',
controller: 'EditSOPCtrl'
})
.otherwise(
{
redirectTo: '/'
})
});
app.controller('HomeCtrl', function($scope) {
});
app.controller('SearchCtrl', function($scope,formsSopSearchCriteria) {
$scope.submitAll = function() {
var searchTerm = $scope.searches.term;
console.log(searchTerm);
var searchPackage={
"offset":0,
"limit":0,
"fields":["record_id","dt_created","created_by","dt_updated","updated_by",149654,149655,149692],
"filters":{"and":[{"field_id":"149655","operator":"contains","value":searchTerm}]},
"sort":{}
};
searchPackage=JSON.stringify(searchPackage);
$scope.searchPackage = searchPackage;
formsSopSearchCriteria.getMatches(searchPackage).success(function(data) {
$scope.sopRecords = data.records;
});
};
$scope.submitSpecific = function() {
var searchPackage = ""
searchPackage=JSON.stringify(searchPackage);
$scope.searchPackage = searchPackage;
formsSopSearchCriteria.getMatches(searchPackage).success(function(data) {
$scope.sopRecords = data.records;
});
};
});
app.factory('formsSopSearchCriteria',function($http) {........
Any ideas? My understanding is that it as an issue of scope. But in the failing example, the partial I provide is mapped to the SearchCtrl in the routeProvider. As a result the model should be available in the controller, just like the example that is working. I suspect I must be missing something, but I am not clear what I am missing.
You need to create $scope.searches as an empty object on initialization:
app.controller('SearchCtrl', function($scope,formsSopSearchCriteria) {
$scope.searches = {};
Or for clarity:
$scope.searches =
{
term: ''
};
If you don't, it will not be created until the first input is entered (I believe it is the $parse service that the ng-model directive uses that creates the searches object in this case).
The problem is that the object might not be created in the scope you want it to.
The reason it works in the first case is because there are no child scopes, so the invoice object is created in the controller scope.
In the second case there is one or many child scopes (probably from the tabs, I haven't dug any deeper into it), so the searches object is created in one of those instead.
Due to how prototypical inheritance works in Javascript, if you predefine the objects in the controllers' scopes, the properties will be created correctly.

Angular repeat bind to independent objects

I have a small Angular application which repeats a list of project objects and allows editing each individual object.
// app.html
<div ng-controller="ProjectsCtrl">
<div ng-repeat="project in projects">
<!-- EDIT -->
<h3>{{ project.id }}</h3>
<h3>{{ project.title }}</h3>
...
<!-- END EDIT -->
<p>
<button class="btn btn-info" ng-click="updateProject(project); showEditProject=true">Edit Project</button>
<button class="btn btn-info" ng-click="showEditProject=false">Cancel</button>
...
</p>
<div class="box row animate-show-hide" ng-show="showEditProject">
<form name="editProjectForm" class="form-horizontal">
<input ng-model="editProject.title" type="text" id="title" name="title" class="form-control" placeholder="Title" required /><br />
...
</form>
</div>
</div>
</div>
// app.js
projectsApp.controller('ProjectsCtrl', function ($scope, $http, ConcernService) {
...
$scope.updateProject = function(obj) {
ConcernService.list('projects/', obj).then(function(){
$scope.editProject = obj;
});
};
This all works fine but as each object is passed on the ng_clickall the editProject objects are bound to the same model. Is it possible to allow the form to open and each object is bound to each project independently?
Your updateProject method in the parent scope is just assigning project to editProject. You can just reference poject in the edit form. There is no need for the editProject field.
// app.html
<div ng-controller="ProjectsCtrl">
<div ng-repeat="project in projects">
<p>
<button class="btn btn-info" ng-click="updateProject(project); showEditProject=true">Edit Project</button>
<button class="btn btn-info" ng-click="showEditProject=false">Cancel</button>
...
</p>
<div class="box row animate-show-hide" ng-show="showEditProject">
<form name="editProjectForm" class="form-horizontal">
<input ng-model="project.title" type="text" id="title" name="title" class="form-control" placeholder="Title" required /><br />
...
</form>
</div>
</div>
</div>
// app.js
projectsApp.controller('ProjectsCtrl', function ($scope, $http, ConcernService) {
...
$scope.updateProject = function(obj) {
ConcernService.list('projects/', obj).then(function(){
$scope.editProject = obj;
});
};
Put the updateProject function in another controller and attach that controller to the div that has the ng-repeat. For example:
projectsApp.controller('ProjectCtrl', funciton($scope, $http, ConcernSerice) {
$scope.updateProject = function(obj) {
ConcernService.list('projects/', obj).then(function(){
$scope.editProject = obj;
});
};
}
and then:
<div ng-repeat="project in projects" ng-controller="ProjectCtrl">
...
</div>
The ng-repeat creates a scope for each project. This will makes it so that when you do $scope.editProject = obj; this will be done on this scope rather than on the single parent scope created by your ProjectsCtrl.
UPDATE:
If you need to be able to reset any edits you made you will need to save a copy of your object. You can probably do this in your updateProject:
$scope.updateProject = function(obj) {
ConcernService.list('projects/', obj).then(function(){
$scope.previousValue = angular.copy(obj);
$scope.editProject = obj;
});
};
Then you would have to create a method for canceling that copies the values back:
$scope.cancel = function(){
$scope.showEditProject = false;
angular.copy($scope.previousValue, $scope.editProject);
};
Then call it from your template:
<button class="btn btn-info" ng-click="cancel()">Cancel</button>

Resources