Perhaps I'm aiming too big with my reusable directive idea, but I've been asked to give a demo for my company in less than two weeks, so I'm aiming higher than normal.
I'm building on top of another question I asked and was answered here:
Angular to do list directive
I've added some new features, such as "Click to edit".
Here's my plnkr
Here's what works:
Here's what I'm having problems with:
- Display text instead of ID from drop down list
- Auto-focus object to force input to have focus so I can really capture blur
Next question will be:
- How do I know what object I'm updating to send back to the server?
I did spend all day Sunday trying to get those tasks to work, but failed. I cleaned up the code of most of my failed attempts.
I do want to save the record each time I edit a field. I get that I'm updating the object, which I think is beautiful, but I don't know what to trigger to send the object back to the server. Perhaps that's the jQuery background talking?
Thanks,
Duane
To display text instead of ID from dropdown list:
You can create a function in the directive that loops through the options, and returns the name
when the id
matches the value you're binding on. For example:
scope.statusText = function(){
var text = '';
angular.forEach(scope.statusOptions, function(item){
if(item.id == scope.task.status)
text = item.name;
});
return text;
}
To auto-focus the element
Create a function in the directive that is called on the ng-click
of the "display" span. This will set scope.editStatusMode = true
, then call .focus
on the element.
scope.setStatusFocus = function(){
scope.editStatusMode = true;
var el = element.find('select');
$timeout(function(){
el.focus();
});
};
Wrapping the el.focus()
in $timeout
will delay the call to focus until the DOM is done rendering. The HTML looks like this:
<span ng-hide="editStatusMode" ng-click="setStatusFocus()" ng-bind="statusText()"></span>
How do you know which object you're updating
Create an update()
function in the directive that is bound to 'ng-blur. In that function, you can access
scope.task`, which you can send off to your server to save.
scope.update = function(){
scope.editPriorityMode = false;
//Save scope.task here.
console.log(scope.task);
}
This works for description
and priority
. It doesn't work for status
because when you change the status, it immediately disappears from whichever list it is in and is added to a different list, and the blur
event is never fired. To deal with status
, you can create a $watch
on task.status
, and call the update()
function from there.
scope.$watch('task.status', function(oldValue, newValue){
scope.update();
})
Plunker
Since you got more than one question I'll answer what I can and then edit with other answers:
Display text instead of ID from drop down list: There is different solutions to this problem. You could use a simple lodash method to find the value of the id you have selected (_.find(priorityOptions, {value: task.priority})
). You could actually save the (id, name)
pair inside your ngModel
(task.priority
) so then you can refer to task.priority.name
in your span.
Auto-focus object to force input to have focus so I can really capture blur: You can call a function inside your ng-click on the span that handles that behaviour and makes sure that the focus will be the input field and also binds a blur event for when you click away.
How do I know what object I'm updating to send back to the server: If you want to send the changes to the server when you blur a field (which, by the way, you can simply do with adding the attribute ng-blur="update()"
to your input elements) you can access the scope
of the element you are on (scope.task
) and send it through a dataFactory
method.