2011-01-17 2 views
2

Мне нужен доступ к определенной модели в макете main.gsp. Я искал вокруг и прочитал, что лучший способ, чтобы получить это, чтобы создать после фильтра и применить модель к парам ViewModel, а затем получить доступ к нему в GSP так:Grails: доступ к модели в макете main.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 в указанном выше фильтре after, он не является нулевым в это время и будет напечатано имя клиента. Я здесь что-то не так? Есть ли лучший способ получить модель внутри main.gsp?

ответ

3

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

How do I (or should I?) access the service layer from a SiteMesh template (views/layouts/main.gsp) in 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 карту, я f, что полезно вообще.

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

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

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

<yournamespace:partnerDetails> 
    This is the body content that will be output in the body() call above. 
</yournamespace:partnerDetails> 
+0

Это не похоже на работу для меня. Я получаю другую ошибку относительно ленивой инициализации, потому что метод isPartner() обращается к части модели, которая является отношением hasMany. Не знаю, почему это происходит ...Тем не менее, я бы предпочел просто иметь клиентский объект, потому что из него есть несколько методов, кроме метода isPartner(). Например, мне также нужен доступ к партнерам. Спасибо, в любом случае! – intargc

+0

Вы действительно должны подумать о решении этого с помощью taglib. Притяжение к большей логике в представлении нарушает концепцию MVC. Может быть, это проще всего, если вы публикуете код taglib, который вы пробовали, и люди могут помочь. – david

+0

Собственно, после чистки он отлично работает в taglib. Однако, поскольку мне действительно нужен доступ к этому методу isPartner(), потому что у меня есть if/else, чтобы отображать некоторые CSS на основе этого условия, а затем требуется идентификатор партнеров, чтобы получить CSS в определенной области, было бы разумно имеют тег типа ... ...? Это даст мне доступ к объекту клиента в основной части этого тега ... Но считается ли это хорошим или плохим? – intargc

1

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

class MyFilters { 
    all(uri: "/**") { 
     ... 
    } 
} 
+0

К сожалению, это тоже не работает ... Я получаю ту же ошибку. Тем не менее, он действительно проходит через контроллер для страницы, на которой я тестирую ее. Мне просто нужно это доступно для всех страниц, так как оно должно быть в main.gsp. – intargc

+0

Может быть проблема с именами. Does '$ {pageScope.getProperty ('client')}' оценивать что-либо в GSP? – ataylor

+0

Как ни странно, если я распечатаю это в своем GSP, я получаю toString() объекта-клиента. Это то, чего я ожидал. Однако я также получаю это исключение: Ошибка оценки выражения [pageScope.getProperty ('client')] в строке [5]: Нет такого свойства: клиент для класса: org.codehaus.groovy.grails.web.pages.GroovyPageBinding – intargc

1

Я хотел бы предложить создать следующие 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() 
    } 
} 
Смежные вопросы