Created
August 3, 2012 04:01
-
-
Save bingomanatee/3244207 to your computer and use it in GitHub Desktop.
race condition - nb-change, form properties
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
```javascript | |
angular.module('skills', ['skillsServices']) | |
.filter('sid', function() { | |
return function(id){ | |
return id.slice(0, 5) + '...'; | |
} | |
}); | |
angular.module('skillsServices', ['ngResource']). | |
factory('Skills', function ($resource) { | |
return $resource('/admin/nerps/skill/:_id', {_id:"@_id"}, { | |
query:{method:'GET', isArray:true}, | |
add:{method:'POST' }, | |
update:{method:'PUT' }, | |
delete:{method:'DELETE'} | |
}); | |
}); | |
function SkillsCtrl($scope, $filter, Skills) { | |
$filter.bases_filter = function(n){ | |
return n.basis == 'mind' | |
} | |
$scope.skills = Skills.query(); | |
console.log('$filter: ', $filter); | |
$scope.orderProp = "name"; | |
$scope.new_skill = {basis:"mind", name:'New Skill', type:"skill"}; | |
$scope.show_add_form = 'none'; | |
$scope.show_edit_form = 'none'; | |
$scope.bases_filters = { | |
mind:true, | |
body:true, | |
reflexes: true, | |
will: true, | |
dex: true, | |
speed: true, | |
senses: true, | |
tough: true | |
} | |
$scope.bases_filter = function(item){ | |
return $scope.bases_filters[item.basis]; | |
} | |
$scope.ensure_bases = function(){ | |
if (! _.filter(_.values($scope.bases_filters), _.identity).length){ | |
_.each(_.keys($scope.bases_filters), function(k){ | |
console.log('truthying ', k); | |
$scope.bases_filters[k] = true; | |
}) | |
} | |
} | |
$scope.bases = [ | |
{ | |
value:'mind', label:'Mind' | |
}, | |
{ | |
value:'ref', label:'Reflexes' | |
}, | |
{ | |
value:'will', label:'Will' | |
}, | |
{ | |
value:'body', label:'Body' | |
} | |
] | |
$scope.revise = function (r) { | |
$scope.editing_skill = r; | |
$scope.edit_skill = _.clone(r); | |
$scope.show_edit_form = 'block'; | |
return false; | |
} | |
$scope.update = function (edit_skill) { | |
console.log('updating ', edit_skill); | |
_.extend($scope.editing_skill, $scope.edit_skill); | |
Skills.update(edit_skill); | |
$scope.show_edit_form = 'none'; | |
return false; | |
} | |
$scope.add = function (new_skill) { | |
$scope.skills.push(Skills.add(new_skill)); | |
$scope.new_skill = {basis:"mind", name:'New Skill', type:"skill"}; | |
$scope.show_add_form = 'none'; | |
} | |
$scope.create = function () { | |
$scope.show_add_form = 'block'; | |
return false; | |
} | |
$scope.delete = function (del) { | |
Skills.delete(del, function(){ | |
$scope.skills = Skills.query(); | |
}) | |
} | |
} | |
SkillsCtrl.$inject=['$scope', '$filter', 'Skills']; | |
``` | |
## Template: | |
``` | |
<style> | |
fieldset.fbb label { | |
display: inline-block; | |
width: 20%; | |
} | |
</style> | |
<div ng-app="skills"> | |
<div ng-controller="SkillsCtrl"> | |
<h1>Skills</h1> | |
<table class="datagrid" style="width: 100%"> | |
<thead> | |
<tr> | |
<td colspan="6" class="controls"> | |
Search <input type="text" value="" class="search_field" ng-model="query"/> <button ng:click="show_fbb=!show_fbb">Filter By Bases</button> | |
<fieldset class="fbb" style="border: 1px solid grey; background-color: #EEE" ng:show=show_fbb><legend>Bases</legend> | |
<label><input type="checkbox" name="bf[]" ng-change="ensure_bases()" ng-model="bases_filters.reflexes" />Reflexes</label> | |
<label><input type="checkbox" name="bf[]" ng-change="ensure_bases()" ng-model="bases_filters.mind"/>Mind</label> | |
<label><input type="checkbox" name="bf[]" ng-change="ensure_bases()" ng-model="bases_filters.will"/>Will</label> | |
<label><input type="checkbox" name="bf[]" ng-change="ensure_bases()" ng-model="bases_filters.body"/>Body</label><br /> | |
<label><input type="checkbox" name="bf[]" ng-change="ensure_bases()" ng-model="bases_filters.dex" />Dexterity</label> | |
<label><input type="checkbox" name="bf[]" ng-change="ensure_bases()" ng-model="bases_filters.senses"/>Senses</label> | |
<label><input type="checkbox" name="bf[]" ng-change="ensure_bases()" ng-model="bases_filters.tough"/>Toughness</label> | |
<label><input type="checkbox" name="bf[]" ng-change="ensure_bases()" ng-model="bases_filters.speed"/>Speed</label></fieldset> | |
</td> | |
</tr> | |
<tr> | |
<th class="id_sort" ng:click="skill_sort='_id'">ID</th> | |
<th class="name_sort" ng:click="skill_sort='name'">Name</th> | |
<th class="basis_sort" ng:click="skill_sort='basis'">Basis</th> | |
<th class="type_sort">Type</th> | |
<th> </th> | |
<th> </th> | |
</tr> | |
</thead> | |
<tbody> | |
<tr ng-repeat="skill in skills | filter:query | filter: bases_filter | orderBy: skill_sort "> | |
<td>{{skill._id | sid }}</td> | |
<td>{{skill.name}}</td> | |
<td>{{skill.basis}}</td> | |
<td>{{skill.type }}</td> | |
<td class="control"> | |
<button class="edit" ng:click="revise(skill)" ><span class="icon"></span> Edit</button> | |
</td> | |
<td class="control"> | |
<button class="delete" ng:click="delete(skill)" ><span class="icon"></span> Delete</button> | |
</td> | |
</tr> | |
</tbody> | |
<tfoot> | |
<tr> | |
<th class="id_sort">ID</th> | |
<th class="name_sort">Name</th> | |
<th class="basis_sort">Basis</th> | |
<th class="type_sort">Type</th> | |
<th> </th> | |
<th> </th> | |
</tr> | |
<tr> | |
<td colspan="6" class="controls"> | |
<button class="add" ng:click="create()">Add Skill | |
</button> | |
</td> | |
</tr> | |
</tfoot> | |
</table> | |
<div class="new_skill" style="display: {{show_add_form}}; background-color: white; color: black"> | |
<form class="dialog_form"> | |
<table> | |
<tr> | |
<td><label>Name</label></td> | |
<td><input type="text" ng-model="new_skill.name"/></td> | |
</tr> | |
<tr> | |
<td><label>Basis</label></td> | |
<td><select ng-model="new_skill.basis"> | |
<option value="reflexes">Reflexes</option> | |
<option value="mind">Mind</option> | |
<option value="will">Will</option> | |
<option value="body">Body</option> | |
<option value="dex">Dex</option> | |
<option value="speed">Speed</option> | |
<option value="senses">Senses</option> | |
<option value="tough">Toughness</option> | |
</select> | |
</td> | |
</tr> | |
<tr> | |
<td><label>Type</label></td> | |
<td><select ng-model="new_skill.type"> | |
<option value="skill">Skill</option> | |
<option value="trait">Trait</option> | |
<option value="race">Race</option> | |
</select> | |
</td> | |
</tr> | |
<tr> | |
<td> </td> | |
<td> | |
<button class="new" ng-click="add(new_skill)">Add Skill</button> | |
</td> | |
</tr> | |
</table> | |
</form> | |
</div> | |
<div class="edit_skill" style="display: {{show_edit_form}}; background-color: rgb(204, 255, 255); color: black"> | |
<form class="dialog_form"> | |
<table> | |
<tr> | |
<td><label>Name</label></td> | |
<td><input type="text" ng-model="edit_skill.name"/></td> | |
</tr> | |
<tr> | |
<td><label>Basis</label></td> | |
<td><select ng-model="edit_skill.basis"> | |
<option value="reflexes">Reflexes</option> | |
<option value="mind">Mind</option> | |
<option value="will">Will</option> | |
<option value="body">Body</option> | |
<option value="dex">Dex</option> | |
<option value="speed">Speed</option> | |
<option value="senses">Senses</option> | |
<option value="tough">Toughness</option> | |
</select> | |
</td> | |
</tr> | |
<tr> | |
<td><label>Type</label></td> | |
<td><select ng-model="edit_skill.type"> | |
<option value="skill">Skill</option> | |
<option value="trait">Trait</option> | |
<option value="race">Race</option> | |
</select> | |
</td> | |
</tr> | |
<tr> | |
<td> </td> | |
<td> | |
<button class="new" ng-click="update(edit_skill)">Update Skill</button> | |
</td> | |
</tr> | |
</table> | |
</form> | |
</div> | |
</div> | |
</div> | |
``` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There is a race condition here - the ensure_bases() kicks off BEFORE the model binding turns off the last checkbox.
The upshot - the goal is that when the last checkbox is unchecked, they ALL become checked.
The actual reault is that they all become checked -- except for the LAST checkbox you check - i.e., the one that triggers the ensure_checked() method in the first place...