learn-co-curriculum / mod3-project-week-setup-example

31 stars 110 forks source link

front-end section is too opinionated and uses evil innerHTML #5

Open geluso opened 5 years ago

geluso commented 5 years ago

TLDR: Opinions ahead! I've found the front-end instructions here too prescriptive. They also include some bad habits (using innerHTML). I think these front-end instructions confuse students. I'm suggesting we should remove them. What do you think?

Removing Front-end Instructions

This guide should be dedicated to showing how students can set up their back end api server. This guide should not burden itself with explaining how to create a front-end. Students should use their knowledge from all the other material in this mod to determine how they want to arrange the frontend. This guide should stop as soon as it shows students how to use fetch to access their server.

The front-end instructions are too prescriptive. It goes in to way too much detail about how to structure everything. It introduces some cool concepts (like the Adapter pattern). Perhaps we can move the front-end guidelines to another reading or lab.

I've seen one student get burned out by following the structure outlined here. They took the pattern too seriously and kept scratching their head wondering why they were doing things this certain way. The text bullet-pointed above waffles back and forth without providing a clear definition of how similar students should follow this pattern. All the instructions together lead students to thinking "this is the One True Way" to build JavaScript applications.

Removing all of these front-end setup instructions would be a better way to prepare students for this. Replace these instructions with more general guidelines that tell students to remember to use classes to encapsulate data and methods, and encourage students to separate their JavaScript code into many files (students tend to make 400+ line mega main.js files).

Here's a diff showing a quick cut-out of unnecessary frontend instructions:

https://github.com/learn-co-students/mod3-project-week-setup-example-seattle-web-career-031119/commit/0d925f7c83ae5a494c0f9026b4242621370d4fe7

innerHTML vs DOM Manipulation

innerHTML is evil. It allows people to create notes with JavaScipt/CSS/HTML that affect the page. Creating elements with string interpolation and innerHTML makes it harder to attach event listeners to elements too.

Preferring to create the elements manually allows us to attach a click listener to the button inside the render method and cleanly pass in parameters to a function that would populate an edit form with the notes properties. It also saves us from having to stuff data into the HTML with the data-id attribute.

renderListItem() {
    return `
    <li>
      <h3>${this.title}
        <button data-id=${this.id}>edit</button>
      </h3>
    </li>`;
  }
renderListItem() {
  let li = document.createElement('li')
  let h3 = document.createElement('h3')
  let button = document.createElement(button')

  h3.textContent = this.title
  button.textContent = 'edit'

  // using createElement allows us to attach click listeners right away!
  button.addEventListener('click', () => {
    renderUpdateForm(this.id, this.title, this.content)
  })

  li.appendChild(h3)
  h3.appendChild(button)
  return li;
}

Simple Custom Routed Controller Example

It would be useful to demystify routes and controllers by creating a super simple custom controller. This example shows how to create two simple GET routes attached to methods that just execute Ruby and return JSON. This shows students they can create routes and controllers that execute any sort of Ruby they can imagine and decouples routes and controllers from ActiveRecord.

config/routes.rb

Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      resources :notes, only: [:index, :update, :create, :destroy]
      get 'my_custom_route', to: 'custom#beef'
      get 'roulette', to: 'custom#roulette'
    end
  end
end

app/controllers/api/v1/custom_controller.rb

class Api::V1::CustomController < ApplicationController
  def beef
    render json: [22, 33, 55]
  end

  def roulette
    choice = [*1..6].sample
    if choice == 1
      render json: 'BANG!'
    else
      render json: 'click'
    end
  end
end
rrcobb commented 5 years ago

Really good note. cc @maxwellbenton

I think that this doc has been filling a gap in the curriculum around how to use rails as an api. Once we have more of that material in place, we can likely turn this into a much more skeletal document, and instead expect that students will tap the skills they'll have practiced at that point.

Re: innerHTML vs. create / append 'real' DOM elements, I find that using innerHTML is easier to follow in cases where the string is short and looks like a 'component'. For the reasons you mention, it's probably a worse pattern to encourage that students use for their project. I think this doc doesn't have to be opinionated about it at all, we have plenty of DOM manipulation content elsewhere. If you want to make a PR to cut that content, I'd approve