0
votes

I'm trying to build a CRUD form using two custom directives. The first one (crudForm) is the main form directive, that holds all of the controls applied to this form (textboxes, textareas, checkboxes, etc.), the second contained (one or many) inside is a directive for custom controls to be included in the form. I want to bind a single object to the main directive (crudForm), and bind each one of the object's fields to one of the child directives inside crudForm. For example, I have an object defined in my $scope as $scope.obj = { "order_id":20, "total": 44.50, "info": "..." }, and to have a form to edit it like

<crud-form key-field="order_id" entity="obj">
  <control type="money" field-name="total" field-title="Total"></control>
  <control type="textarea" field-name="info" field-title="Information"></control>
</crud-form>

I have a full example here.

The thing is that I want to automatically bind the object in the main controller, first to the form, and then each field to the controls, so that when there is a change in the input, the object bound will be changed as well. I can't do this, because as far as I have seen in the console log, the control's link function executes before the form's link function, so at the time the control's link function is being executed, the object bound to the form's link function isn't instanciated.

Any ideas?

1

1 Answers

0
votes

Here is a modified Plunkr in which (only) the input of total is working and binded to obj: http://plnkr.co/edit/OjEzjZeUC2yTKkaoFEoP

Removed this code from form.js (it was throwing errors anyway because you can not access entity like this):

element.find('[rel=input]').on('change', function() {
  $scope.$parent.entity[$scope.field.name] = $(this).val();
}).val($scope.$parent.entity[$scope.field.name]);

Added this to the controller code of crudForm:

this.getEntity = function() { return $scope.entity; };

In directive control changed the link function declaration from

post: function($scope, element, $attrs) {

to this, thus adding a reference to the parent controller.

post: function($scope, element, $attrs, parentCtrl) {

By the way: Write $scope as scope and $attrs as attrs. These arguments are position-fixed and not magically working by name. So avoid confusion.

Then I added this code to the link function in control:

$scope.entity = parentCtrl.getEntity();

Then I fixed script.js (you are setting different keys than you are referencing in index.html!) and as an example changed the code from money.tpl.html to this:

<div class="input-prepend">
    <span class="add-on">{{ field.options.symbol }}</span>
    <input type="text" id="field-{{ field.name }}" class="input-small" rel="input" ng-model="entity[field.name]"/>
</div>

The change here is ng-model="entity[field.name]". So as you can see, with the changes before you can just use entity in your child directive and directly bind to the referenced attribute / object. No actual need to copy any values.