Skip to content

Instantly share code, notes, and snippets.

@bingomanatee
Created August 3, 2012 04:01
Show Gist options
  • Save bingomanatee/3244207 to your computer and use it in GitHub Desktop.
Save bingomanatee/3244207 to your computer and use it in GitHub Desktop.
race condition - nb-change, form properties
```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>&nbsp;</th>
<th>&nbsp;</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>&nbsp;</th>
<th>&nbsp;</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>&nbsp;</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>&nbsp;</td>
<td>
<button class="new" ng-click="update(edit_skill)">Update Skill</button>
</td>
</tr>
</table>
</form>
</div>
</div>
</div>
```
@bingomanatee
Copy link
Author

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...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment