2

I have a custom directive - let's call it tableDisplay. I want to be able to show/hide a column based on an attribute (we'll call it show-edit-column which I have working) BUT I also want to be able to, on each row, determine whether or not the given row is editable. I'd like to do this by passing in another attribute (allow-edit-row-condition) that tells the conditional statement each row should use to determine whether its editable or not.

Something like the following.

<table-display show-edit-column="true" allow-edit-row-condition="row.value === 'OK'">

I just don't know how to pass row.value === 'OK' in a way that can then be used on each row. Any ideas/suggestions?

9
  • If the row is created with ng-repeat add the allow-edit-row-condition attribute to each repeated element? Commented Dec 4, 2014 at 22:20
  • 1
    The problem is the allow-edit-row-condition can change depending on the page the table-display directive is used on, so it needs to be customizable. Commented Dec 4, 2014 at 22:22
  • what is row.value? Is row defined in the parent scope of your directive? Commented Dec 4, 2014 at 22:22
  • Nope - that's the problem. row is defined inside the table-display directive. So what I'm trying to do is pass a condition into the directive to be evaluated inside the directive. Commented Dec 4, 2014 at 22:24
  • 1
    why not just pass a function directly? Commented Dec 5, 2014 at 0:10

2 Answers 2

2

Pass a function.

On your parent scope define

$scope.isEditAllowedForRow = function (row) {
   return (row.value === 'OK');
};

Directive scope parameter declared as one-way binding:

...
allowEditRowCondition: '&'
...

And use it as

<table-display show-edit-column="true"
               allow-edit-row-condition="isEditAllowedForRow(row)">

Now, in your directive template you can use the condition as

allowEditRowCondition({row: row})

e.g.

<tr ng-show="allowEditRowCondition({row: row})">

In Javascript always think about functions.

Sign up to request clarification or add additional context in comments.

2 Comments

Now the directive requires polluting the scope with functions that operate on its internals - doesn't seem like the best approach to me.
Sulthan - thank you! Going to try it out now. New Dev - the upside is that its being used by myself only for now and at worst by other coworkers.
1

I understand the question. You are trying to pass a text expression of condition that can be evaluated in the context of your internal ng-repeat. I would probably advise against that because now your clients have to understand your internal directive structure, because row is meaningless in the parent scope (i.e. to the consumers of your directive).

But if you insist...

You'd need to interpolate this expression in the context of each row. So, parse the expression into a function to be exposed on the internal scope. You can do this in your link function:

link: function(scope, elem, attrs){
  // get the condition as string
  var cond = attrs["condition"];

  // parse to create a function
  var matcher = $parse(cond);

  scope.matchRow = function(row){
    // evaluate the function in the context of the row
    return matcher({row: row});
  };

Then, in your view you could filter based on this condition:

<tr ng-repeat="row in src | filter:matchRow">
  <td ng-repeat="col in row">{{col}}</td>
</tr>

Or, perform some conditional rendering (editable vs. not):

<tr ng-repeat="row in src">
  <td ng-repeat="col in row">
    <input ng-disabled="!matchRow(row)" ng-model="col" class="form-control">
  </td>
</tr>

Here's a plunker to illustrate

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.