0

I have a section of my app for "Client Invoices" which includes 2 components [for now]: Invoice List and New Invoice Modal Form.

The view looks like this:

%h2 Client Invoices

%div(ng-controller="ClientInvoicesCtrl as clientInvoicesCtrl")

  %div(ng-controller="NewInvoiceModalCtrl as newInvoiceModal")
    %a.button(href="#' ng-click="newInvoiceModal.open()") + New Invoice

  %table
    %thead
      %tr
        %th Client
        %th Invoice #
        ...
    %tbody
      %tr(ng-repeat="invoice in clientInvoices")
        %td {{ invoice.client.name}} ({{invoice.client.id}})
        %td {{ invoice.id }}
        ...

And my logic is this:

app.controller 'ClientInvoicesCtrl', ['$http', '$scope', ($http, $scope) ->
  $scope.clientInvoices = []
  $http
    .get '/clients/invoices.json'
    .success (data) ->
      $scope.clientInvoices = data.client_invoices
]

app.controller 'NewInvoiceModalCtrl', ['$modal', ($modal) ->
  @open = ->
    modalInstance = $modal.open {
      templateUrl: '/clients/invoices/new'
      controller: 'NewInvoiceModalInstanceCtrl'
      windowClass: 'small'
    }
]

app.controller 'NewInvoiceModalInstanceCtrl', ['$scope', '$modalInstance', ($scope, $modalInstance) ->
  $scope.clientInvoice = {
    id: ''
    client_id: ''
    start_on: new Date()
    amount: ''
  }

  $scope.save = ->
    # need to push $scope.clientInvoice into ClientInvoicesCtrl.clientInvoices
    $modalInstance.close()
]

So there's a controller that wraps the entire section and then a modal controller within that.

What I want to do is feed from the NewInvoiceModalInstanceCtrl into the ClientInvoicesCtrl to pass the newly created invoice in the modal to the invoices list. I attempted to change towards a service to communicate between the 2 controllers with the following:

app.factory 'InvoicesSrvc', ->
  return { clientInvoices: [] }

app.controller 'ClientInvoicesCtrl', ['$http', '$scope', 'InvoicesSrvc', ($http, $scope, InvoicesSrvc) ->
  $scope.clientInvoices = InvoicesSrvc.clientInvoices
  $http
    .get '/clients/invoices.json'
    .success (data) ->
      InvociesSrvc.clientInvoices.concat data.client_invoices
]

...

app.controller 'NewInvoiceModalInstanceCtrl', ['$scope', '$modalInstance', 'InvoicesSrvc', ($scope, $modalInstance, InvoicesSrvc) ->
  ...

  $scope.save = ->
    # need to push $scope.clientInvoice into ClientInvoicesCtrl.clientInvoices
    InvoicesSrvc.clientInvoices.push $scope.clientInvoice

    # ... post request to submit to server ...
    $modalInstance.close()
]

This doesn't seem to work though. There seems to be a problem when using Array#concat with bindings.

I've created a GitHub Gist for the 2 versions (see revisions) of my code.

6
  • possible duplicate of What's the correct way to communicate between controllers in AngularJS? Commented Jul 7, 2014 at 13:55
  • That's where I thought I'd find my answer, but I think the root of my problem is really around Array#concat and binding to it. Commented Jul 7, 2014 at 13:58
  • Did you tried instead of InvociesSrvc.clientInvoices.concat data.client_invoices using an actual method that you could invoke with InvociesSrvc.addClientInvoice(data.client_invoices) ? Commented Jul 7, 2014 at 14:03
  • Also, you have a typo in your code... InvociesSrvc.clientInvoices.concat data.client_invoices while the factory is named InvoicesSrvc Commented Jul 7, 2014 at 14:04
  • @domokun The code is not directly copied to protect some of the data in the code. I haven't tried a #addClientInvoice method yet. I'm still having trouble getting the binding to work between clientInvoices and the table when I use Array#concat in my HTTP response. Commented Jul 7, 2014 at 14:08

1 Answer 1

1

Instead of using an empty array that gets referenced from the outside like this:

app.factory 'InvoicesSrvc', ->
  return { clientInvoices: [] }

...

//later in the code
InvociesSrvc.clientInvoices.concat data.client_invoices

You can write a factory which stores the same array, but exposes some methods to manipulate the data. A simple structure like this one can do the trick:

app.factory('InvoiceSrvc', function () {

  // your private data (and eventually functions) goes here
  var clientInvoices = []

  // your public API gets returned here
  return {

    addClientInvoice: function (invoice) {
      clientInvoices.push(invoice)
    }

  }      
})

Then you can, of course, add every method you may need to manipulate the array.

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

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.