5

I have been working on implementing AngularJS into my Rails app based on the Railscast as a starting point. My question is similiar to this question: Angular JS ngResource with nested resources, however I have not found a solution to my problem.

Currently I have a nested resource which I am displaying on the view of the parent resource, via a partial. I need to supply the project_id in the query in order to retrieve the tasks, so I have:

app.factory "Task", ["$resource", ($resource) ->
  $resource("/projects/:project_id/tasks/:id", {project_id: "@project_id", id: "@id"}, {update: {method: "PUT"}})
]

@TaskCtrl = ["$scope", "Task", ($scope, Task) ->
  $scope.tasks = Task.query({project_id: "@project_id", id: "@id"})

My question is, how do I set '@project_id' in the view so that on the last line in my example the value is accessible in the controller? I tried using ng-init:

<div ng-controller="TaskCtrl" ng-init="project_id = <%= @project.id %>">

However once in my TaskCtrl controller 'project_id' is blank, and '$scope.project_id' does not work either. Any help is appreciated.

3 Answers 3

5

ng-init runs before template execution, not before controller init. If only the template is aware of the project_id, create a shared service (it can be a simple value factory) which holds the project id and inject it to your controller. You can fill that service from another controller initialised before TaskController

<div ng-controller="ProjectIDController">
    <span ng-init="project_id = <%= @project.id %>"></span>
</div>

<div ng-controller="TaskCtrl">
    ...
</div>

function ProjectIDController( $scope, sharedService ) {
    $scope.$watch('project_id', function (UID) {
        sharedService.setProjectID($scope.project_id);
    });
}

function TaskCtrl ($scope, Task, sharedService) {
    $scope.tasks = Task.query({project_id: sharedService.getProjectId()... 
}

sorry for not coffee...

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

4 Comments

Thanks for the response, Olivér. Question: If ng-init is being accessed by ProjectID Controller, why can I not move the project_id span into Task Controller? Granted I am new to angularjs, but it seems like if values are included within the Controller they should be accessible from the scope.
Sure, you can do that, but you still have to $watch the project_id, since it does not have a value on controller init. But if you need the project_id in another controller, sibling for TaskCtrl, it wont see project_id, only children will. Thats where the service came along.
Thanks for all your help but this wasn't quite working for me ... I used the gon gem to pass in the value. It seems like acquiring normal field values from the view should be a bit easier in AngularJS.
I can't get this working, can you explain what the sharedService factory would look like?
0

While this doesn't solve the problem via AngularJS, I ended up just passing in the value via the gon gem:

projects controller:

  def show
    gon.project_id = @project.id
    .
    .
  end

coffee js file:

$scope.tasks = Task.query({project_id: gon.project_id})

1 Comment

I get gon is not defined when using this method. Any ideas?
0

gon isn't a good solution

http://docs.angularjs.org/api/ng.directive:ngInit

or you can try this

2 Comments

why is gon a bad solution?
it seems to me that it breaks angularjs philosophy and single page pattern

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.