kemalcr / kemal

Fast, Effective, Simple Web Framework
https://kemalcr.com
MIT License
3.65k stars 189 forks source link

How to pass variables to layout script #619

Closed lebogan closed 3 years ago

lebogan commented 3 years ago

Description

This works in kemal 1.0.0 The route:

macro my_renderer(filename)
    render "src/views/#{{{filename}}}.slang", "src/views/layouts/layout.slang"
end

get "/about" do |env|
    title = "About"
    my_renderer "about"
end

The layout file(slang):

doctype html
html lang="en-US"
  head
    title== title

Expected behavior: [What you expect to happen] I expect to see the page title on the browser tab.

Actual behavior: [What actually happens] Worked on v1.0.0. Fails on 1.1.0 Error: undefined local variable or method 'title' for ...

Reproduces how often: [What percentage of the time does it reproduce?] 100%

Versions

crystal v1.1.1 kemal v1.0.0, v1.1.0 ubuntu 20.04lts

Additional Information

Any additional information, configuration or data that might be necessary to reproduce the issue.

lebogan commented 3 years ago

Lots of head scratching and version swapping I tried something dumb (for me!). I moved the title to the subview template and removed it from the layout template. And, voila. Why? My original purpose was to pass the title variable into the layout file. Should I move this to a forum? This is clearly my misunderstanding of how Kemal works. Thanks.

henrikac commented 3 years ago

@lebogan I think the reason why it doesn't work in v1.1.0 is because the dependency on Kilt was removed. Users should either use Crystal's built-in ECR or add a 3rd party template engine.

Maybe this is something that should be mentioned on the Kemal website @sdogruyol ?

Edit (2022-09-29):

I just found out that Kilt was not removed in v1.1.0. It will, however, be removed in a future version. I'm not sure why this issue happens but have you tried to use content_for and yield_content?

lebogan commented 3 years ago

@henrikac, I have tried to use those and failed miserably. Here's what I have tried, using slang, of course. The layout:

doctype html
html lang="en-US"
  head
    == yield_content "page_title"
    meta charset="utf-8"
    meta name="viewport" content="width=device-width, initial-scale=1"
    ...

The web page:

== content_for "page_title" do 
    title== "WebApp"

Viewing the page source shows a blank space where the title would be inserted. My first thought is that I am doing this incorrectly. I have tried more using -, =, and == to no avail. Also played around with indentation. By the way, using title== WebApp in the web page works though for the life of me, I can't figure out why. Thanks for any insight.

henrikac commented 3 years ago

@lebogan I'm not sure why you're getting that error but this works just fine for me

Crystal: 1.1.1
Kemal: 1.1.0

shard.yml

dependencies:
  kemal:
    github: kemalcr/kemal
  slang:
    github: jeromegn/slang

src/main.cr

require "kemal"
require "kilt/slang"

macro my_renderer(filename)
  render "src/views/#{{{filename}}}.slang", "src/views/layouts/layout.slang"
end

get "/about" do |env|
  title = "About"
  my_renderer "about"
end

Kemal.run

src/views/layouts/layout.slang

doctype html
html lang="en-US"
  head
    title== title

src/views/about.slang

h1 Hello from about

My only issue is that "Hello from about" is not being rendered but this might be because I'm not familiar with slang :)

lebogan commented 3 years ago

Thanks @henrikac. I am going to close this as it seems more my misunderstanding than an issue with Kemal. I appreciate all the responses.