Ограбление: Как вставить динамический список суб-шаблонов в шаблон?

Я пишу сайт для онлайн-опросов. У меня есть список вопросов, которые все идут на одной странице HTML, и список имеет неизвестную длину. Каждый вопрос имеет форму, хранящуюся в шаблоне qu1.tpl и страница qu.tpl, Теперь я хочу:

  1. заменить некоторые имена в qu1.tpl за каждый вопрос

  2. заменить некоторые вещи в qu.tpl один раз

  3. и придерживаться всех экземпляров qu1.tpl в qu.tpl

Используя то, что я узнал из учебника, я попытался рекурсивно заменить тег <qulist/> с <apply template="qu1.tpl"><qulist/> в qu.tpl с помощью localHeist а также bindString но это не может работать, потому что qu.tpl уже отображается, поэтому вновь вставленный тег применения не разрешается.

что я должен сделать вместо этого?

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

3 ответа

В Heist, когда вы делаете что-то, что связано с вычислениями на динамических данных, вы обычно будете использовать соединение. Ваши первые две точки могут быть обработаны с помощью связующих соединений. Что касается третьего пункта, я бы начал с создания функции сплайсинга, которая отображает конкретный шаблон вопроса. Это будет выглядеть примерно так:

questionSplice :: Monad m => Int -> Splice m
questionSplice n = do
  splices <- setupSplicesForThisQuestion
  mTemplate <- callTemplate (B.pack ("qu"++(show n))) splices
  return $ fromMaybe [] mTemplate

Теперь вы можете создать соединение для списка вопросов опроса:

surveyQuestions :: Monad m => Splice m
surveyQuestions = do
  questions <- getSurveyQuestions
  mapSplices questionSplice questions

Затем вы можете привязать это соединение к определенному тегу и использовать его где угодно в qu.tpl или любом другом шаблоне.

Важной частью здесь является функция callTemplate. Это функция Heist для рендеринга шаблонов внутри вычисления TemplateMonad. Я не думаю, что об этом много говорится в руководствах, потому что это не тот случай использования, которым обычно занимаются люди, и его легко пропустить в документации по API.

Спасибо Mightybyte за помощь мне с этим на IRC. после 8 часов, когда мне было запрещено отвечать на вопросы, вот мой вариант ответа:

  1. создать сплайс, который читает шаблон qu1.tpl, создает его экземпляр (то есть, заполняет имя и номер вопроса в списке) и возвращает его. в этом вам поможет функция ограбления callTemplate. (этот сплайс называется сплайсексом в псевдокоде ниже.)

  2. напишите другой сплайс, который сворачивает сплайсекс так, чтобы вы получили список (созданных) вопросов вместо одного. (функция сплайсинга в псевдокоде.)

  3. используйте bindSplice вместо bindString.

псевдокод (протестирован, затем модифицирован и вырван из контекста) -

 ... -> let
          splice :: Monad m => Splice m
          splice = foldM (\ ts (s, i) ->
                             liftM ((++) ts) $ splicex (quName, quNumber))
                         []
                         (zip questionName [0..])

          splicex :: Monad m => (String, Int) -> Splice m
          splicex (quName, quNumber) =
              do
                mt <- callTemplate "qu1"
                        [ ("question-name", Data.Text.pack quName)
                        , ("question-number", Data.Text.pack $ show quNumber)
                        ]

                case mt of
                  Nothing -> error "splice rendering failed."
                  Just (t :: Template) -> return t
         in
           -- fill in the list of (instatiated) questions
           heistLocal (bindSplice "qulist" splice) $
           -- before that, instantiate the overall page
           instantiatePage $
           render "qu"

Кстати, мой аватар sourceforge слишком слаб, чтобы создавать новые теги. Кто-нибудь хочет пометить это с "ограблением"?

ссылки по теме:

http://snapframework.com/

#snapframework канал в сети IRC freenode.

http://snapframework.com/docs/tutorials/heist

Когда я попытался выяснить циклы шаблонов, я несколько раз сталкивался с этим вопросом. К сожалению, все здесь, вероятно, устарело, версия 0.5 (или ниже), в то время как версия 0.6 (я предполагаю) представила runChildrenWith.

Простой пример использования runChildrenWith:

list_test_entries.tpl:

<listTestEntries>
  <dt><testEntry/></dt>
  <dd>This is part of the repeated template</dd>
</listTestEntries>

Site.hs:

listTestEntriesHandler :: Handler App App  ()
listTestEntriesHandler = do
    results <- getData 
    renderWithSplices "list_test_entries"
        ("listTestEntries" ## listTestEntriesSplice results)

getData :: Handler App App [String]
getData = return ["1", "2", "3"]

listTestEntriesSplice  :: [String] -> I.Splice AppHandler
listTestEntriesSplice = I.mapSplices (I.runChildrenWith . listTestEntrySplice)

listTestEntrySplice :: Monad m => String -> Splices (HeistT n m Template)
listTestEntrySplice dataEntry = do
  "testEntry" ## I.textSplice (T.pack $ "data: " ++ dataEntry)

См. https://github.com/michaxm/heist-template-loop-demo для запуска демонстрации.

Другие вопросы по тегам