ga-wdi-exercises / project3

[Project, Mongo, Mongoose, Node, Express, React, API] Prompt for 3rd WDI Project using React, Node, Mongo, Express and Mongoose
3 stars 4 forks source link

defining multiple state params from different factories #432

Closed justwes2 closed 7 years ago

justwes2 commented 7 years ago

We have a page where I want to add an instances of attendances, our join table. The function is called on an event page, and the user selects from a dropdown of students. I'm trying to figure out how to define the student ID by the dropdown selection and the event ID by the event page. What I have so far is:

this.addAttendance = function() {
        let attendance = {
          student_id: this.student.id,
          event_id: this.event.id
        }
      }

but that's erroring out at this.student= StudentFactory.query({id: $stateParams.id}); saying that query is expecting an array but getting an object. I'm not sure how to identify the student based on the selection in the dropdown menu.

AndyWhitley commented 7 years ago

You want to use StudentFactory.get() for querying for a specific instance of a student.

AndyWhitley commented 7 years ago

Also, you are going to want to feed StudentFactory.get() an object with an id: property equal to the value retrieved from the dropdown menu (same as you did in the second part of the movie browser HW).

justwes2 commented 7 years ago

Ok, so I've added an ng-model = "vm.studentGoing" to the ng-repeat options. I also updated the code like so:

     this.studentGoing = 'sg';
     this.student= StudentFactory.get({vm.studentGoing.id: $stateParams.id});

based on the movie browser assignment (I used jquery, but I sense that introducing that library here would add complication). Now the browser says that the period after vm is unexpected and throws an error. In addition, this.student, when console logged, says that the module failed to instantiate.

AndyWhitley commented 7 years ago

The ng-model directive would go on the select html element. If it is, default behavior will modify whatever is bound to ng-model to be whatever the value attribute is on the currently selected option within it (which is the html element that ng-repeat will be attached to).

Then in your controller, you will query the StudentFactory using the value of studentGoing: this.student= StudentFactory.get({id: this.studentGoing});

AndyWhitley commented 7 years ago

Also check out the documentation for more advanced configurations for using select with angular:\ https://docs.angularjs.org/api/ng/directive/select

justwes2 commented 7 years ago

So in the options html <option ng-repeat="student in vm.students" >{{student.name}}</option> I should add value = "student.id?

AndyWhitley commented 7 years ago

Yes exactly.

justwes2 commented 7 years ago

I am also getting an error that the 'link' module is not loaded, but that is the 2nd line of code in our js file, which is being loaded, because the behavior causing the error is defined in that same file further down...

AndyWhitley commented 7 years ago

could you post a screenshot of the error and a code snippet of your current app.js?

justwes2 commented 7 years ago

Screenshot: screen shot 2017-03-14 at 1 31 17 pm Error page: https://docs.angularjs.org/error/$injector/modulerr?p0=link&p1=Error:%20%5B$injector:nomod%5D%20http:%2F%2Ferrors.angularjs.org%2F1.3.15%2F$injector%2Fnomod%3Fp0%3Dlink%0A%20%20%20%20at%20https:%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.15%2Fangular.min.js:6:417%0A%20%20%20%20at%20https:%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.15%2Fangular.min.js:21:412%0A%20%20%20%20at%20a%20(https:%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.15%2Fangular.min.js:21:53)%0A%20%20%20%20at%20https:%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.15%2Fangular.min.js:21:296%0A%20%20%20%20at%20https:%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.15%2Fangular.min.js:35:46%0A%20%20%20%20at%20r%20(https:%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.15%2Fangular.min.js:7:302)%0A%20%20%20%20at%20g%20(https:%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.15%2Fangular.min.js:34:399)%0A%20%20%20%20at%20ab%20(https:%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.15%2Fangular.min.js:38:135)%0A%20%20%20%20at%20d%20(https:%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.15%2Fangular.min.js:17:381)%0A%20%20%20%20at%20uc%20(https:%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.15%2Fangular.min.js:18:179

Code snippets: module:

angular
  .module("link", [
    "ui.router",
    "ngResource"
  ])

controller function:

   function linkShowEventControllerFunction(eventFactory, $stateParams, AttendanceFactory, StudentFactory){
     this.event = eventFactory.get({id: $stateParams.id});
     this.attendances = AttendanceFactory.query({id: $stateParams.id});
     this.students= StudentFactory.query();
     this.student= StudentFactory.get({id: this.studentGoing});
     console.log(this.student)
      this.addAttendance = function() {
        let attendance = {
          student_id: this.student.id,
          event_id: this.event.id
        }
      }
   }
superbuggy commented 7 years ago

Can you include your code for eventFactory and AttendanceFactory as well?

justwes2 commented 7 years ago

Event Factory:

function eventFactoryFunction($resource){
      return $resource("http://localhost:3000/events/:id.json", {}, {
        update: {method: "PUT"}
      })
    }

Attendance Factory:

function attendanceFactoryFunction($resource){
      return $resource("http://localhost:3000/events/:id/attendances.json", {}, {
        update: {method:"PUT"}
      })
    }
superbuggy commented 7 years ago

It seems like there are 2 distinct errors here, bad config (badcfg) for $resource and the module injection. is the module injection a side-effect of another error?

superbuggy commented 7 years ago

How is your rails app responding? What happens when you go to localhost:3000/events/13.json & localhost:3000/events/13/attendances.json?

Doesn't have to be 13 specifically, just the id of an extant event in your db

justwes2 commented 7 years ago

It is more than possible. If there is an error, its coming from the addAttendance function. http://localhost:3000/events/1/attendances.json lists the seed data and some half formed instanced that don't have a student associated with them.

AndyWhitley commented 7 years ago

post a code snippet of your entire app.js file so I can check the connections

justwes2 commented 7 years ago
angular
  .module("link", [
    "ui.router",
    "ngResource"
  ])
  .config([
    "$stateProvider",
    RouterFunction
  ])
  .controller("welcomeController",[
    welcomeControllerFunction
  ])
  .controller(
    "StudentIndexController", [
      "StudentFactory",
      "$stateParams", StudentIndexControllerFunction
    ])
  .controller(
    "StudentShowController", [
      "StudentFactory",
      "$stateParams", StudentShowControllerFunction
    ])
    .controller(
      "AttendanceIndexController", [
        "AttendanceFactory",
        "$stateParams", AttendanceIndexControllerFunction
      ])
  .controller(
    "StudentNewController",
    [ "StudentFactory", "$state", StudentNewControllerFunction
  ])
  .controller( "StudentEditController", [
      "StudentFactory",
      "$stateParams",
      StudentEditControllerFunction
    ])
    .controller("linkEventIndexController", [
      "eventFactory",
      "$stateParams",
      linkEventIndexControllerFunction
    ])
    .controller("linkNewEventController", [
      "eventFactory",
      linkNewEventControllerFunction
    ])
    .controller("linkShowEventController", [
      "eventFactory",
      "$stateParams",
      "AttendanceFactory",
      "StudentFactory",
      linkShowEventControllerFunction
    ])
    .controller("linkEventEditController", [
      "eventFactory",
      "$stateParams",
      linkEventEditControllerFunction
    ])
  .factory( "StudentFactory", [ "$resource", StudentFactoryFunction ])
  .factory("eventFactory", [
    "$resource",
    eventFactoryFunction
  ])
  .factory("AttendanceFactory", [
    "$resource",
    attendanceFactoryFunction
  ])

    function eventFactoryFunction($resource){
      return $resource("http://localhost:3000/events/:id.json", {}, {
        update: {method: "PUT"}
      })
    }
      function StudentFactoryFunction($resource){
        return $resource("http://localhost:3000/students/:id.json", {}, {
          update: {method: "PUT"}
        })
      }

    function attendanceFactoryFunction($resource){
      return $resource("http://localhost:3000/events/:id/attendances.json", {}, {
        update: {method:"PUT"}
      })
    }

    function RouterFunction($stateProvider){
      $stateProvider
      .state("welcome",{
        url: "/",
        templateUrl: "js/ng-views/welcome.html",
        controller: "welcomeController",
        controllerAs: "vm"
      })
      .state ("studentIndex", {
          url: "/students",
          templateUrl: "js/ng-views/students/index.html",
          controller: "StudentIndexController",
          controllerAs: "vm"
        })
      .state("studentNew", {
           url: "/students/new",
           templateUrl: "js/ng-views/students/new.html",
           controller: "StudentNewController",
           controllerAs: "vm"
     })
     .state("studentShow", {
          url: "/students/:id",
          templateUrl: "js/ng-views/students/show.html",
          controller: "StudentShowController",
          controllerAs: "vm"
        })
      .state("attendanceIndex", {
            url: "/events/:id/attendances",
            templateUrl: "js/ng-views/attendances/index.html",
            controller: "AttendanceIndexController",
            controllerAs: "vm"
           })
      .state("studentEdit", {
          url: "/students/:id/edit",
          templateUrl: "js/ng-views/students/edit.html",
          controller: "StudentEditController",
          controllerAs: "vm"
        })
        .state("eventIndex", {
          url:"/events",
          templateUrl: "js/ng-views/events/index.html",
          controller: "linkEventIndexController",
          controllerAs: "vm"
        })
        .state("eventNew", {
          url: "/events/new",
          templateUrl: "js/ng-views/events/new.html",
          controller: "linkNewEventController",
          controllerAs: "vm"
        })
        .state("eventShow", {
          url: "/events/:id",
          templateUrl: "js/ng-views/events/show.html",
          controller: "linkShowEventController",
          controllerAs: "vm"
        })
        .state("eventEdit", {
          url: "/events/:id/edit",
          templateUrl: "js/ng-views/events/edit.html",
          controller: "linkEventEditController",
          controllerAs: "vm"
        })
    }

    function StudentIndexControllerFunction (StudentFactory){
      console.log("you're in the index")
      this.students = StudentFactory.query();
    }

    function AttendanceIndexControllerFunction (AttendanceFactory, $stateParams){
      console.log("you're in the attendance index")
      this.attendances = AttendanceFactory.query({id: $stateParams.id});
    }

    function StudentNewControllerFunction(StudentFactory, $state){
     this.student = new StudentFactory()
     this.create = function(){
       this.student.$save().then(function(student){
         $state.go("studentShow",{id: student.id})
       })
     }
   }
    function StudentShowControllerFunction (StudentFactory, $stateParams){
      this.student = StudentFactory.get({id: $stateParams.id})
    }

    function StudentEditControllerFunction( StudentFactory, $stateParams ){
     this.student = StudentFactory.get({id: $stateParams.id});
     this.update = function(){
       this.student.$update({id: $stateParams.id})
     }
     this.destroy = function(){
        this.student.$delete({id: $stateParams.id}).then(function(student){
          $state.go("studentIndex")
        })
      }
   }
   function linkEventIndexControllerFunction(eventFactory){
     console.log("you're in the event index")
     this.events = eventFactory.query();
   }

   function linkNewEventControllerFunction(eventFactory){
     this.event = new eventFactory();
     this.create = function(){
       this.event.$save().then(function(event){
         $state.go("eventShow",{id: event.id})
       })
     }
   }

   function linkShowEventControllerFunction(eventFactory, $stateParams, AttendanceFactory, StudentFactory){
     this.event = eventFactory.get({id: $stateParams.id});
     this.attendances = AttendanceFactory.query({id: $stateParams.id});
     this.students= StudentFactory.query();
    //  this.studentGoing = 'sg';
     this.student= StudentFactory.get({id: this.studentGoing});
    //  let studentString =   JSON.stringify(this.students);
     console.log(this.student)
    //  console.log(studentString)

      this.addAttendance = function() {
        let attendance = {
          student_id: this.student.id,
          event_id: this.event.id
        }
      }
   }

   function linkEventEditControllerFunction(eventFactory, $stateParams){
     this.event = eventFactory.get({id: $stateParams.id});
     this.update = function(){
       this.event.$update({id: $stateParams.id});
     }
     this.destroy = function(){
       this.event.$delete({id: $stateParams.id});
     }
   }

   function welcomeControllerFunction(){

   }
AndyWhitley commented 7 years ago
  1. Standardize your casing for naming your factories and their related functions and your indentations

  2. You do not need .json at the end of the $resource configuration:

      function StudentFactoryFunction($resource){
        return $resource("http://localhost:3000/students/:id", {}, {
          update: {method: "PUT"}
        })
      }
  3. Not sure if it matters, but try moving all of your .factory definitions above all of your .controller definitions in the chain at the top of your app.js file

justwes2 commented 7 years ago

I overhauled the script.js, but I am still getting an error that $resource does not match the configured parameter (looking for object but got array), as well as a pair of 406 errors (not acceptable) from the rails server.

justwes2 commented 7 years ago
angular
  .module("link", [
    "ui.router",
    "ngResource"
  ])
  .config([
    "$stateProvider",
    RouterFunction
  ])
  .factory( "studentFactory", [
    "$resource",
    studentFactoryFunction ])
    .factory("eventFactory", [
      "$resource",
      eventFactoryFunction
    ])
    .factory("AttendanceFactory", [
      "$resource",
      attendanceFactoryFunction
    ])
  .controller("welcomeController",[
    welcomeControllerFunction
  ])
  .controller(
    "studentIndexController", [
      "studentFactory",
      "$stateParams",
      studentIndexControllerFunction
  ])
  .controller(
    "studentShowController", [
      "studentFactory",
      "$stateParams",
      studentShowControllerFunction
  ])
  .controller(
    "attendanceIndexController", [
      "AttendanceFactory",
      "$stateParams",
      attendanceIndexControllerFunction
  ])
  .controller(
    "studentNewController",[
       "studentFactory",
       "$state",
       studentNewControllerFunction
  ])
  .controller(
    "studentEditController", [
      "studentFactory",
      "$stateParams",
      studentEditControllerFunction
  ])
  .controller("eventIndexController", [
    "eventFactory",
    "$stateParams",
    eventIndexControllerFunction
  ])
  .controller("newEventController", [
    "eventFactory",
    newEventControllerFunction
  ])
  .controller("showEventController", [
    "eventFactory",
    "$stateParams",
    "AttendanceFactory",
    "studentFactory",
    showEventControllerFunction
  ])
  .controller("eventEditController", [
    "eventFactory",
    "$stateParams",
    eventEditControllerFunction
  ])

function eventFactoryFunction($resource){
  return $resource("http://localhost:3000/events/:id", {}, {
    update: {method: "PUT"}
  })
}

function studentFactoryFunction($resource){
  return $resource("http://localhost:3000/students/:id", {}, {
    update: {method: "PUT"}
  })
}

function attendanceFactoryFunction($resource){
  return $resource("http://localhost:3000/events/:id/attendances", {}, {
    update: {method:"PUT"}
  })
}

function RouterFunction($stateProvider){
  $stateProvider
    .state("welcome",{
      url: "/",
      templateUrl: "js/ng-views/welcome.html",
      controller: "welcomeController",
      controllerAs: "vm"
    })
    .state ("studentIndex", {
      url: "/students",
      templateUrl: "js/ng-views/students/index.html",
      controller: "studentIndexController",
      controllerAs: "vm"
    })
    .state("studentNew", {
       url: "/students/new",
       templateUrl: "js/ng-views/students/new.html",
       controller: "studentNewController",
       controllerAs: "vm"
    })
    .state("studentShow", {
      url: "/students/:id",
      templateUrl: "js/ng-views/students/show.html",
      controller: "studentShowController",
      controllerAs: "vm"
    })
    .state("attendanceIndex", {
      url: "/events/:id/attendances",
      templateUrl: "js/ng-views/attendances/index.html",
      controller: "attendanceIndexController",
      controllerAs: "vm"
    })
    .state("studentEdit", {
      url: "/students/:id/edit",
      templateUrl: "js/ng-views/students/edit.html",
      controller: "studentEditController",
      controllerAs: "vm"
    })
    .state("eventIndex", {
      url:"/events",
      templateUrl: "js/ng-views/events/index.html",
      controller: "eventIndexController",
      controllerAs: "vm"
    })
    .state("eventNew", {
      url: "/events/new",
      templateUrl: "js/ng-views/events/new.html",
      controller: "newEventController",
      controllerAs: "vm"
    })
    .state("eventShow", {
      url: "/events/:id",
      templateUrl: "js/ng-views/events/show.html",
      controller: "showEventController",
      controllerAs: "vm"
    })
    .state("eventEdit", {
      url: "/events/:id/edit",
      templateUrl: "js/ng-views/events/edit.html",
      controller: "eventEditController",
      controllerAs: "vm"
    })
}

function studentIndexControllerFunction (studentFactory){
  console.log("you're in the index")
  this.students = studentFactory.query();
}

function attendanceIndexControllerFunction (AttendanceFactory, $stateParams){
  console.log("you're in the attendance index")
  this.attendances = AttendanceFactory.query({id: $stateParams.id});
}

function studentNewControllerFunction(studentFactory, $state){
 this.student = new studentFactory()
 this.create = function(){
   this.student.$save().then(function(student){
     $state.go("studentShow",{id: student.id})
   })
 }
}

function studentShowControllerFunction (studentFactory, $stateParams){
  this.student = studentFactory.get({id: $stateParams.id})
}

function studentEditControllerFunction( studentFactory, $stateParams ){
 this.student = studentFactory.get({id: $stateParams.id});
 this.update = function(){
   this.student.$update({id: $stateParams.id})
 }

 this.destroy = function(){
    this.student.$delete({id: $stateParams.id}).then(function(student){
      $state.go("studentIndex")
    })
  }
}

function eventIndexControllerFunction(eventFactory){
 console.log("you're in the event index")
 this.events = eventFactory.query();
}

function newEventControllerFunction(eventFactory){
 this.event = new eventFactory();
 this.create = function(){
   this.event.$save().then(function(event){
     $state.go("eventShow",{id: event.id})
   })
 }
}

function showEventControllerFunction(eventFactory, $stateParams, AttendanceFactory, studentFactory){
 this.event = eventFactory.get({id: $stateParams.id});
 this.attendances = AttendanceFactory.query({id: $stateParams.id});
 this.students= studentFactory.query();
//  this.studentGoing = 'sg';
 this.student= studentFactory.get({id: this.studentGoing});
//  let studentString =   JSON.stringify(this.students);
 console.log(this.student)
//  console.log(studentString)

  this.addAttendance = function() {
    let attendance = {
      student_id: this.student.id,
      event_id: this.event.id
    }
  }
}

function eventEditControllerFunction(eventFactory, $stateParams){
 this.event = eventFactory.get({id: $stateParams.id});
 this.update = function(){
   this.event.$update({id: $stateParams.id});
 }
 this.destroy = function(){
   this.event.$delete({id: $stateParams.id});
 }
}

function welcomeControllerFunction(){

}
superbuggy commented 7 years ago

can you post your rails controllers code?

justwes2 commented 7 years ago

Events:

class EventsController < ApplicationController

  def index
    @events = Event.all
    render json: @events
  end

  def show
    @event = Event.find(params[:id])
    render json: @event
  end

  def new
    @event = Event.new
  end

  def create
      @event = Event.new(event_params)
        if @event.save!
          render json: @event, status: :created
        else
          render json: @message.errors, status: :unprocessable_entity
        end
  end

  def edit
    @event = Event.find(params[:id])
  end

  def update
    @event = Event.find(params[:id])
      if @event.update!(event_params)
        render json: @event
      else
        render json: @message.errors, status: :unprocessable_entity
      end
  end

  def destroy
    @event = Event.find(params[:id])
    @event.destroy
    render json: {message: "success"}, status: :ok
  end

  private
  def event_params
    params.require(:event).permit(:date, :time, :name, :location, :organizer, :event_url)
  end
end

Attendances:

class AttendancesController < ApplicationController

  def index
    @event = Event.find(params[:event_id])
    # @attendances = Attendance.all
    @attendances = @event.attendances
    respond_to do |format|
      # format.html {render :index}
      format.json {render json: @attendances}
    end
  end

  def new
    @event = Event.find(params[:event_id])
    @attendance = @event.attendances.new
  end

  def create
    @event = Event.find(attendance_params[:event_id])
    puts "====================#{attendance_params[:event_id]}"
    puts "====================#{attendance_params[:student_id]}"
    @student = Student.find(attendance_params[:student_id])

    puts "+=+=+=+=+=+=+=+=+ event:#{@event}"
    puts "+=+=+=+=+=+=+=+=+ student:#{@student.inspect}"
    existing_attendance = Attendance.find_by(event: @event, student: @student)
    unless existing_attendance
      puts "+=+=+=+=+=+=+=+=+ I'm here"
      @attendance = @event.attendances.create!(comment: attendance_params[:comment], student: @student)
    end
    respond_to do |format|
      if @attendance.save
        format.html { redirect_to @event, notice: 'Attendance was successfully created.' }
        format.json { render json: @attendance, status: :created }
      else
        format.html { render :new }
        format.json { render json: @attendance.errors, status: :unprocessable_entity }
      end
    end
    # redirect_to event_path(@event)
  end

  private
  def attendance_params
    params.require(:attendance).permit(:student_id, :event_id, :comment)
  end

end

Students:

class StudentsController < ApplicationController

  def index
    @students = Student.all
    render json: @students
  end

  def show
    @student = Student.find(params[:id])
    render json: @student
  end

  def new
    @student = Student.new
  end

  def create
    @student = Student.new(student_params)
      if @student.save!
        render json: @student, status: :created
      else
        render json: @message.errors, status: :unprocessable_entity
      end
    end

  def edit
    @student = Student.find(params[:id])
  end

  def update
    @student = Student.find(params[:id])
    if @student.update!(student_params)
      render json: @student
    else
      render json: @message.errors, status: :unprocessable_entity
    end
  end

  def destroy
    @student = Student.find(params[:id])
    @student.destroy
    render json: {message: "success"}, status: :ok
  end

  private
  def student_params
    params.require(:student).permit(:date, :time, :name, :location, :organizer, :student_url)
  end
end
superbuggy commented 7 years ago

Thanks!

Okay, does adding .json back in your Factory paths alleviate the 406 error?

superbuggy commented 7 years ago

Sorry, where exactly does the badcfg error seem to happen?

superbuggy commented 7 years ago
 this.student= studentFactory.get({id: this.studentGoing});

is this.studentGoing an integer?

justwes2 commented 7 years ago

adding the .json back did fix the 406 errors. studentGoing is identified here on the show page:

<select class="rsvp" name="rsvp" ng-model="vm.studentGoing">
        <option ng-repeat="student in vm.students" value = "student.id" >{{student.name}}</option> </select>

It looks like the 'GET' action is what is causing the error.

superbuggy commented 7 years ago

It looks like the 'GET' action is what is causing the error.

.get() is still somehow receiving a collection, right?

justwes2 commented 19 minutes ago I overhauled the script.js, but I am still getting an error that $resource does not match the configured parameter (looking for object but got array)

AndyWhitley commented 7 years ago

In the AttendanceIndexControllerFunction, you had AttendanceFactory.query({id: $stateParams.id}). .query() takes no input:

AttendanceFactory.query()
justwes2 commented 7 years ago

@superbuggy the object when console logged is a bunch of stuff surrounding a bad config error.

@AWhitleyGA could we use .find() then, since we need to show only those instances where the attendance's event ID matches the event's id, and that params is what was doing it for us.

AndyWhitley commented 7 years ago

In the ShowEventControllerFunction, this.studentGoing should not be defined when the view loads, it should only be defined when addAttendance is triggered:

function ShowEventControllerFunction(EventFactory, $stateParams, AttendanceFactory, StudentFactory){
  this.event = EventFactory.get({id: $stateParams.id});
  this.attendances = AttendanceFactory.query();
  this.students= studentFactory.query();
  this.addAttendance = function() {
    this.student= studentFactory.get({id: this.studentGoing});
    let attendance = {
      student_id: this.student.id,
      event_id: this.event.id
    }
    //here you will use AttendanceFactory to post new Attendance to API
  }
}
AndyWhitley commented 7 years ago

You will want to load them in using .query() and then use a .filter() to filter the collection in the related angular controller.

AndyWhitley commented 7 years ago

Also, you should use CapitalCase for Factory and Controller names and functions. Only state names in the router function should use camelCase. I've updated your code to consistently use this convention and fix the bug listed above:

angular
  .module("link", [
    "ui.router",
    "ngResource"
  ])
  .config([
    "$stateProvider",
    RouterFunction
  ])
  .factory("StudentFactory", [
    "$resource",
    StudentFactoryFunction
  ])
  .factory("EventFactory", [
    "$resource",
    EventFactoryFunction
  ])
  .factory("AttendanceFactory", [
    "$resource",
    AttendanceFactoryFunction
  ])
  .controller("welcomeController",[
    WelcomeControllerFunction
  ])
  .controller("StudentIndexController", [
    "StudentFactory",
    "$stateParams",
    StudentIndexControllerFunction
  ])
  .controller("studentShowController", [
    "StudentFactory",
    "$stateParams",
    StudentShowControllerFunction
  ])
  .controller("attendanceIndexController", [
    "AttendanceFactory",
    "$stateParams",
    AttendanceIndexControllerFunction
  ])
  .controller("StudentNewController",[
    "StudentFactory",
    "$state",
    StudentNewControllerFunction
  ])
  .controller("StudentEditController", [
    "StudentFactory",
    "$stateParams",
    StudentEditControllerFunction
  ])
  .controller("EventIndexController", [
    "EventFactory",
    "$stateParams",
    EventIndexControllerFunction
  ])
  .controller("NewEventController", [
    "EventFactory",
    NewEventControllerFunction
  ])
  .controller("ShowEventController", [
    "EventFactory",
    "$stateParams",
    "AttendanceFactory",
    "StudentFactory",
    ShowEventControllerFunction
  ])
  .controller("EventEditController", [
    "EventFactory",
    "$stateParams",
    EventEditControllerFunction
  ])

function EventFactoryFunction($resource){
  return $resource("http://localhost:3000/events/:id", {}, {
    update: {method: "PUT"}
  })
}

function StudentFactoryFunction($resource){
  return $resource("http://localhost:3000/students/:id", {}, {
    update: {method: "PUT"}
  })
}

function AttendanceFactoryFunction($resource){
  return $resource("http://localhost:3000/events/:id/attendances", {}, {
    update: {method:"PUT"}
  })
}

function RouterFunction($stateProvider){
  $stateProvider
    .state("welcome",{
      url: "/",
      templateUrl: "js/ng-views/welcome.html",
      controller: "WelcomeController",
      controllerAs: "vm"
    })
    .state ("studentIndex", {
      url: "/students",
      templateUrl: "js/ng-views/students/index.html",
      controller: "StudentIndexController",
      controllerAs: "vm"
    })
    .state("studentNew", {
       url: "/students/new",
       templateUrl: "js/ng-views/students/new.html",
       controller: "StudentNewController",
       controllerAs: "vm"
    })
    .state("studentShow", {
      url: "/students/:id",
      templateUrl: "js/ng-views/students/show.html",
      controller: "StudentShowController",
      controllerAs: "vm"
    })
    .state("attendanceIndex", {
      url: "/events/:id/attendances",
      templateUrl: "js/ng-views/attendances/index.html",
      controller: "AttendanceIndexController",
      controllerAs: "vm"
    })
    .state("studentEdit", {
      url: "/students/:id/edit",
      templateUrl: "js/ng-views/students/edit.html",
      controller: "StudentEditController",
      controllerAs: "vm"
    })
    .state("eventIndex", {
      url:"/events",
      templateUrl: "js/ng-views/events/index.html",
      controller: "EventIndexController",
      controllerAs: "vm"
    })
    .state("eventNew", {
      url: "/events/new",
      templateUrl: "js/ng-views/events/new.html",
      controller: "NewEventController",
      controllerAs: "vm"
    })
    .state("eventShow", {
      url: "/events/:id",
      templateUrl: "js/ng-views/events/show.html",
      controller: "ShowEventController",
      controllerAs: "vm"
    })
    .state("eventEdit", {
      url: "/events/:id/edit",
      templateUrl: "js/ng-views/events/edit.html",
      controller: "EventEditController",
      controllerAs: "vm"
    })
}

function StudentIndexControllerFunction (StudentFactory){
  console.log("you're in the index")
  this.students = StudentFactory.query();
}

function AttendanceIndexControllerFunction (AttendanceFactory, $stateParams){
  console.log("you're in the attendance index")
  this.attendances = AttendanceFactory.query();
}

function StudentNewControllerFunction(StudentFactory, $state){
 this.student = new StudentFactory()
 this.create = function(){
   this.student.$save().then(function(student){
     $state.go("studentShow",{id: student.id})
   })
 }
}

function StudentShowControllerFunction (StudentFactory, $stateParams){
  this.student = StudentFactory.get({id: $stateParams.id})
}

function StudentEditControllerFunction( StudentFactory, $stateParams ){
 this.student = StudentFactory.get({id: $stateParams.id});
 this.update = function(){
   this.student.$update({id: $stateParams.id})
 }

 this.destroy = function(){
    this.student.$delete({id: $stateParams.id}).then(function(student){
      $state.go("studentIndex")
    })
  }
}

function EventIndexControllerFunction(EventFactory){
 console.log("you're in the event index")
 this.events = EventFactory.query();
}

function newEventControllerFunction(EventFactory){
 this.event = new EventFactory();
 this.create = function(){
   this.event.$save().then(function(event){
     $state.go("eventShow",{id: event.id})
   })
 }
}

function ShowEventControllerFunction(EventFactory, $stateParams, AttendanceFactory, StudentFactory){
  this.event = EventFactory.get({id: $stateParams.id});
  this.attendances = AttendanceFactory.query();
  this.students= studentFactory.query();
  this.addAttendance = function() {
    this.student= studentFactory.get({id: this.studentGoing});
    let attendance = {
      student_id: this.student.id,
      event_id: this.event.id
    }
    //here you will use AttendanceFactory to post new Attendance to API
  }
}

function EventEditControllerFunction(EventFactory, $stateParams){
 this.event = EventFactory.get({id: $stateParams.id});
 this.update = function(){
   this.event.$update({id: $stateParams.id});
 }
 this.destroy = function(){
   this.event.$delete({id: $stateParams.id});
 }
}

function WelcomeControllerFunction(){

}
superbuggy commented 7 years ago

You can pass params into .query() tho

superbuggy commented 7 years ago

Let's stick with isolating the the source of the badcfg error is that is still happening. Either the endpoint in the Rails Back-End is doing something unexpected, or maybe the Factory is hitting the asking for the the wrong route for some reason.

This line in particular is what I'm wondering about:

    this.student= studentFactory.get({id: this.studentGoing});

Is vm.studentGoing/this.studentGoing definitely an integer? Passing an argument with an unexpected value into .get may be causing it to return a collection.

To debug that, let's throw in some asynchronously-handled console.logs. We have to wait on a response from the server to get the data back and log it.

Debugging statements should go either in a callback or a promise:

//90% sure about this syntax. $promise is a property, not a function. I believe you need to expose the `$promise` object in this way to use `.then()` with. if that doesn't work try just `.then()` without $promise
this.event = EventFactory.get({id: $stateParams.id}).$promise.then( res => console.log(res) );

// OR callback style
this.event = EventFactory.get({id: $stateParams.id}, res => console.log(res) );
superbuggy commented 7 years ago

These debugging statements can go in your controllers wherever you are using the .get Factory/$resource method.

Again I assume you are still getting that same badcfg error.

justwes2 commented 7 years ago

I have an ajax function:

unction addAttendance(AttendanceFactory, attendance) {
      let url = `http://localhost:3000/events/${event.id}/attendances.json`
      $http({
        method: "POST",
        url: url,
        dataType: "json",
        data: attendance
      }).done((response) => {
        console.log('sucess')
      }).fail(() => {
        console.log('error')
      }).always(() => {
        console.log('request made')
      })
    }
  }

but it's not doing anything when I click the ng-submit tagged button. I can tell I'm doing something wrong since I don't call the factory in the function, but the angular docs only referenced a cacheFactory in the $http info. I checked the weather and movie browser homeworks, but neither of them used factories, just straight api calls. Are there more relevant resources I should be checking to figure out how to get this function to work?

superbuggy commented 7 years ago

but it's not doing anything when I click the ng-submit tagged button

This seems very important to figure out. Last time I saw you had this issue, it seemed like you had some lingering files in your repo which were causing some file-management confusion.

justwes2 commented 7 years ago

Yesterday we had some issues with non-referenced js files, but we've deleted them to clean house. The repo is here: https://github.com/laurkgol/Front_End_Link_Proj_3. The form that is supposed to be controlling the firing of this POST request is on the show event view:

  <form >
      <select class="rsvp" name="rsvp" ng-model="vm.studentGoing">
        <option ng-repeat="student in vm.students" value = "student.id" >{{student.name}}</option>
      </select>
      <button type="submit" value="Submit" ng-submit = "vm.addAttendance()">I'm going</button>
    </form>
superbuggy commented 7 years ago

Make sure your seed data will reliably help you test:

in seeds.rb

Attendance.create(
  student_id: 1,
  event_id: 1,
  comment: "test of thing"
)

change to


Attendance.create(
  student_id: Student.first.id,
  event_id: Event.first.id,
  comment: "test of thing"
)
justwes2 commented 7 years ago

Ok, I swapped out the seeds and reset the db. It still shows up correctly. What does that tell me?

superbuggy commented 7 years ago

It's just a loose end to tie up, we wouldn't want the hardcoded values to cause us problems if they didn't line up with the database ids. We want something to come back when we grab the attendances for a certain event, specifically in this case, the first event. We need reliable test data in order to test.

I'm debugging the other problem right now

superbuggy commented 7 years ago

I don't know why ng-submit isn't binding to the form. try ng-click.

    this.student= studentFactory.get({id: this.studentGoing});

again, this line. it has another issue: studentFactory isn't defined

superbuggy commented 7 years ago

Also,

<option ng-repeat="student in vm.students" value="student.id">{{student.name}}</option>

should be:

<option ng-repeat="student in vm.students" value={{student.id}}>{{student.name}}</option>
superbuggy commented 7 years ago

I would remove the AJAX and use .$save also.

justwes2 commented 7 years ago

I made the changes to the show view, but I'm a little unclear on the js side.

function ShowEventControllerFunction(EventFactory, $stateParams, AttendanceFactory, StudentFactory){
  this.event = EventFactory.get({id: $stateParams.id});
  this.attendances = AttendanceFactory.query({id: $stateParams.id});
  this.students= StudentFactory.query();
  this.addAttendance = function() {
    this.student= studentFactory.get({id: this.studentGoing});
    let attendance = {
      student_id: this.student.id,
      event_id: this.event.id
    }
    //here you will use AttendanceFactory to post new Attendance to API
    function addAttendance(AttendanceFactory, attendance) {
      let url = `http://localhost:3000/events/${event.id}/attendances.json`
      $http({
        method: "POST",
        url: url,
        dataType: "json",
        data: attendance
      }).done((response) => {
        console.log('sucess')
      }).fail(() => {
        console.log('error')
      }).always(() => {
        console.log('request made')
      })
    }
  }
}

student factory is defined in the controller function, and I'm not calling ajax anywhere, so would the .$save go in place of the $http?

superbuggy commented 7 years ago

Do something like this in ShowEventControllerFunction:

vm.newAttendance = new AttendanceFactory()
//rework your form to use the above with ng-model
//i.e. vm.newAttendance.event_id, vm.newAttendance.student_id

this.addAttendance = function() {
    vm.newAttendance.$save().then( res => console.log(res) )
justwes2 commented 7 years ago

Here is my updated function:

function addAttendance(AttendanceFactory, attendance) {
      vm.newAttendance = new AttendanceFactory()

      this.create= function() {
        this.attendance.$save(function(attendance) {
          $state.go("eventShow", {id: event.id})
        })
      }

and here is where I added the ng-model to the form:

<form >

      <select class="rsvp" name="rsvp" ng-model="vm.studentGoing">
       <option ng-repeat="student in vm.students" value={{student.id}} ng-model = "vm.newAttendance">{{student.name}}</option>

      </select>
      <button type="submit" value="Submit" ng-click = "vm.addAttendance()">I'm going</button>
    </form>

Its not throwing errors, but its not logging anything so I'm not sure how to debug. I know the server can accept stuff from postman, so there's an issue with the method on this side.

superbuggy commented 7 years ago
        this.attendance.$save(function(attendance) {
        // change to
        this.newAttendance.$save(function(attendance) {
superbuggy commented 7 years ago
          $state.go("eventShow", {id: event.id})
          // change to
          $state.go("eventShow", {id: attendance.event.id})
justwes2 commented 7 years ago

Made both changes, no change in output, no errors.