vapor / template-kit

📄 Easy-to-use foundation for building powerful templating languages in Swift.
MIT License
46 stars 17 forks source link

Data not displaying #14

Closed grosch closed 6 years ago

grosch commented 6 years ago

I'm having an issue with data not appearing on the HTML page and was pointed here. I've got an Order class that defines a bunch of properties, and uses CodingKeys to modify the names in the database:

final class Client: Codable, SoftDeletable {
    static var deletedAtKey: WritableKeyPath<Client, Date?> = \.deleted

    var id: Int? = nil

    var name: String
    var pointsPerMonth = 0.0
    // rest removed for brevity

    enum CodingKeys: String, CodingKey {
        case id
        case name
        case pointsPerMonth = "points_per_month"
        // rest removed for brevity
    }

and then on my controller I've got a simple method to show all the elements:

func clientIndexHandler(_ req: Request) throws -> Future<View> {
    return Client.query(on: req).all().flatMap(to: View.self) { clients in
        print(clients[0].pointsPerMonth)
        let context = ClientIndexContent(clients: clients.isEmpty ? nil : clients.sorted { $0.name.caseInsensitiveCompare($1.name) == .orderedAscending })
        return try req.leaf().render("client", context)
    }
}

When I run the app and load the page I see the expected value for pointsPerMonth printed out in Xcode's console from the print statement. However, there's no value in the HTML. The .leaf file just uses a simple table to show the data:

  <tbody>
    #for(client in clients) {
      <tr>
        <td>
          <a href="/clients/#(client.id)/edit"><img src="/images/edit.png" /></a>&nbsp;<a href="/clients/#(client.id)/delete"><img src="/images/delete.png" /></a>
        </td>
        <td>#(client.name)</td>
        <td>#(client.pointsPerMonth)</td>
        <td>#(client.monthlyRate)</td>
        <td>#(client.ratePerPoint)</td>
        <td>#(client.overageRate)</td>
        <td>#(client.contractStart)</td>
        <td>#(client.contractEnd)</td>
        <td>#if(client.canRollover){<img src="/images/checkmark.png" class="mx-auto d-block" />}</td>
        <td>#if(client.canBorrow){<img src="/images/checkmark.png" class="mx-auto d-block" />}</td>
        <td>#if(client.prepaid){<img src="/images/checkmark.png" class="mx-auto d-block" />}</td>
      </tr>
    }
  </tbody>

The first, second, and last <td> elements have data. Everything else is blank.

0xTim commented 6 years ago

@grosch I'm gonna guess that client.points_per_month works - the coding keys will affect the data going into Leaf as well since they all rely on Codable

grosch commented 6 years ago

@0xTim Ugh! That's what the issue was. That's horrible though. The coding keys are supposed to make the database work, but the whole res of the project should use the variables as defined by Swift. Very confusing to have everything use the pascal case names, and then the leaf file only use the snake case.

0xTim commented 6 years ago

Well everything that uses Swift will use how they are defined in the Swift. But Leaf needs to convert the data into something it can understand so it uses Codable for that - it will be the same for JSON. If you are returning JSON you'll get the snake_case keys

tanner0101 commented 6 years ago

Closing since this is related to Codable itself.