AngularJs Directives with DropDown lists

2019-09-02 21:22发布

问题:

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:

  • Click to edit

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

回答1:

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



回答2:

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.