Grails: доступ к модели в макете main.gsp - PullRequest
2 голосов
/ 17 января 2011

Мне нужен доступ к конкретной модели в моем макете main.gsp. Я искал и прочитал, что лучший способ получить это - создать фильтр после и применить модель к параметру viewModel, а затем получить к нему доступ в gsp следующим образом:

class MyFilters {
    all(controller:'*', action:'*') {
        after = {viewModel ->
            viewModel.client = Client.get(session.clientId)
            // println "Client is: ${client.toString()}"
        }
    }
}

А в моем GSP я должен получить "клиента" и иметь возможность получить к нему доступ?

<g:if test="${client.isPartner()}">
    Do something
</g:if>
<g:else>
    Do something else
</g:else>

Примером того, что я пытаюсь сделать, являются шаблоны GSP и конкретные таблицы стилей CSS, основанные на том, принадлежит ли текущий клиент, вошедший в систему, партнеру. Расположение специальных шаблонов CSS и GSP зависит от имени партнера, например:

<g:if test="${client.isPartner()}">
    <link rel="stylesheet" type="text/css" href="/partners/${client.getPartner().toString()}/css/style.css"/>
</g:if>
<g:else>
    <link rel="stylesheet" type="text/css" href="/partners/default/css/style.css"/>
</g:else>

Это также будет сделано с шаблонами GSP ... Однако, когда я делаю это, я получаю исключение:

ERROR grails.web.pages.GroovyPagesServlet  - Original exception : Cannot invoke method isPartner() on null object

Итак, очевидно, "клиент" в GSP является нулевым. Если я раскомментирую println в фильтре после, показанном выше, он не будет нулевым в это время, и будет напечатано имя клиента. Я что-то здесь не так делаю? Есть ли лучший способ получить модель внутри main.gsp?

Ответы [ 3 ]

3 голосов
/ 18 января 2011

Это похоже на дубликат вопроса, на который я недавно ответил. Я предложил решить эту проблему с помощью библиотеки тегов:

Как мне (или я должен?) Получить доступ к служебному слою из шаблона SiteMesh (views / layouts / main.gsp) в Grails?

У вас есть доступ к сеансу в теге lib, поэтому закрытие, похожее на это, должно работать:

...
static namespace = "yournamespace"
...
def partnerDetails = { attrs, body ->
    def client = Client.get(session.clientId)
    if (client.isPartner()) {
        out << "Whatever you want to write out..."
                    // You can also call other tag libs from here - see docs
    }
    }
...

Затем вы используете тег в своем gsp что-то вроде этого:

<yournamespace:partnerDetails />

Вы также можете передавать атрибуты, которые передаются в замыкание через карту attrs, если это вообще полезно.

Наконец, если вы хотите условно отобразить тело тега, вы можете сделать это следующим образом:

...
if (client.isPartner()) {
    out << body()
}
....

И вы бы назвали это так:

<yournamespace:partnerDetails>
    This is the body content that will be output in the body() call above.
</yournamespace:partnerDetails>
1 голос
/ 18 января 2011

Я бы предложил создать следующую TagLib:

<g:ifPartner id="123">This client is a partner</g:ifPartner>

Соответствующий код будет выглядеть примерно так:

def isPartner = { attrs, body ->

  def id = attrs.remove('id')
  if (Client.get(id)?.isPartner()) {
    out << body()
  }
}
1 голос
/ 18 января 2011

Этот фильтр будет соответствовать только запросам, которые проходят через контроллер.Если вы направляетесь непосредственно к представлению в UrlMappings.groovy, оно не попадет в цель.Попробуйте что-то вроде этого, чтобы отфильтровать URL-адреса независимо от того, проходят ли они через контроллер.

class MyFilters {
    all(uri: "/**") {
        ...
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...