AngularJS - Losing controller scope within method

486 views Asked by At

Angular noob here. I'm trying to create a form as a directive. ng-submit calls a controller action, but, within that method, I don't have access to the controllers scope, ie. $scope.

Here's the part that's really confusing me. On my laptop and my desktop, the first time I dropped into debugger within the submit(), $scope was still in scope. Every subsequent time, it's not.

I had a coworker test this code, and they can't reproduce it.

EDIT: If I do not drop into debugger at that point in $scope.submit it works fine.

course-material-form.js.coffee

angular
  .module 'app'
  .directive 'courseMaterialForm', () ->
    restrict: 'EA'
    templateUrl: 'app/shared/coursework/course-material/templates/_form.html'
    scope:
      book: '='
      model: '='
    controller: 'CourseMaterialFormCtrl'

course-material-form-ctrl.js.coffee

angular
  .module 'app'
  .controller 'CourseMaterialFormCtrl', ($scope) ->
    $scope.submit = () ->

    return

_form.html.haml

%form.form-compact#course-material-form{ "ng-submit" => "submit()" }
  %fieldset.row
    .form-group.col-xs-12
      %label Title
      %input{ type: 'text', "ng-model" => " book.title " }

    .form-group.col-md-6.col-xs-12
      %label Author
      %input{ type: 'text', "ng-model" => " book.author " }

  %fieldset.row
    .form-group.col-md-6.col-xs-12
      %label Publisher
      %input{ type: 'text', "ng-model" => " book.publisher " }

    .form-group.col-md-6.col-xs-12
      %label Publication Year
      %input{ type: 'text', "ng-model" => " book.publication_date " }

    .form-group.col-md-6.col-xs-12
      %label Edition
      %input{ type: 'text', "ng-model" => " book.edition " }

    .form-group.col-md-6.col-xs-12
      %label ISBN
      %input{ type: 'text', "ng-model" => " book.isbn " }

  %fieldset.row
    .form-group.col-xs-12
      %label Description
      %textarea{ "ng-model" => "book.description" }

  %fieldset.row.hidden
    .form-group.col-md-6.col-xs-6
      %label URL
      %input{ type: 'text' }

_modal.html.haml

.modal-dialog.modalbox-dialog.coursework-form-modal
  .modal-content

    %header.modal-header.modal-header-lg
      .modal-heading
        %span{ "ng-if" => "!book" } Add
        %span{ "ng-if" => "book" } Edit
        Course Material

      %button.modal-close-btn.modal-close-icon{ "ng-click" => "$dismiss()" }
        %i.fa.fa-times-circle

    .modal-body
      %course-material-form{ model: "model", book: "book" }

    .modal-footer
      %button.btn.btn-primary.modal-footer-btn{ form: "course-material-form",
                                                type: "submit" }
        %span{ "ng-if" => "!book" } Create
        %span{ "ng-if" => "book" } Save
      %button.btn.btn-outline.modal-footer-btn{ "ng-click" => "$dismiss()",
                                                type: "button" }
        Close
2

There are 2 answers

0
kjprice On BEST ANSWER

I don't know if this qualifies as an answer. I was not actually calling $scope from within the controller method. If you $scope.book then $scope is available in the debugger.

2
ThiagoPXP On

The submit function from your controller and from your directive are not the same. They belong to different $scope. More info about it on section "Isolating the Scope of a Directive" from the Directive's guide

Since you are isolating the scope for the directive, you should "expose" the submit function from your controller to your directive like that:

scope: {
    book: '=',
    model: '=',
    submit: '&' // <- that's what you need
}

Then on your _modal.html, pass the a new attribute:

.modal-body
    %course-material-form{ model: "model", book: "book", submit: "submit()" }