1

In Vapor, specifically in the class for a custom Leaf tag, how can you retrieve values stored in a context?

I'm trying to implement a tag that takes a string and a path, and renders a link unless the path is the current page, so, for example, #navElement("About Us", "/about") will produce a link to the site's about page on every page except the about page itself. On that page, it should display the text without a link on it.

I don't want to have to pass the current path to the tag every time I use it, so I've stored the request's path in the context, roughly like this (checks omitted):

drop.get(":page"){ request in
  return try drop.view.make(thePage, ["path": request.uri.path])
}

I can use #(path) in a template and see the path I expect.

My custom tag is derived from Tag, and its run method receives the context as an argument, and I can see the stored value in there in the debugger – but how do I get at it? The get method in the Context class, which seems to do this, is internal, so I can't use it. There is a comment that says subscripts are to be done, and I assume that this will ultimately be the way to extract values from the context, but in the meantime, is there any way to retrieve them?

Caleb Kleveter
  • 11,170
  • 8
  • 62
  • 92
MacAvon
  • 15
  • 3

1 Answers1

0

Just make the current path one of the arguments to your tag.

Droplet route:

drop.get(":page") { request in
  return try drop.view.make(thePage, ["currentPath": request.uri.path])
}

In template:

#navElement("About Us", "/about", currentPath)

Tag:

class NavElement: Tag {

  let name = "navElement"

  public func run(stem: Stem, context: LeafContext, tagTemplate: TagTemplate, arguments: [Argument]) throws -> Node? {
    guard
      let linkText = arguments[0].value?.string,
      let linkPath = arguments[1].value?.string,
      let currentPath = arguments[2].value?.string
    else { return nil }
    if linkPath == currentPath {
      return Node("We are at \(currentPath)")
    } else {
      return Node("Link \(linkText) to \(linkPath)")
    }
  }

}

Edit:

I have spoken to the developers of Vapor, and they do not intend to open up access to Context's contents publicly. However, since the queue: List<Node>() is public, you can just copy the get() function into your own extension and then you'll be able to do as you wanted.

tobygriffin
  • 5,339
  • 4
  • 36
  • 61
  • Thanks, but I'm trying to avoid repeating that argument every time I use the tag, and since I have the context in the `run` method already, I was hoping to be able to extract the path from there. – MacAvon Nov 08 '16 at 09:50
  • Thanks for finding this out. Seems like an odd decision, when they are passing the context to `run`, but mine not to reason why. The suggested workaround does the trick for me. – MacAvon Nov 09 '16 at 13:47