Переменные Scala/Twirl и область видимости/определение

Я фронтенд по профессии, но меня попросили перейти к проекту Scala, который использует платформу Play, включая Twirl. Я пытаюсь создать шаблон, который отображает несколько разные результаты в зависимости от переданной строки.

Вот мой код:

@(status: String)(implicit messages: Messages)

@{
    if(status == "00") {
        val pageTitle = "Page title"
        val appStatus = "className"
        val title = "message"
        val subTitle = "message"
        val step1Status = "className"
        val step2Status = "className"
        val step3Status = "className"
        val image1 = "/customs/assets/images/image.png"
        val image2 = "/customs/assets/images/image.png"
        val image3 = "/customs/assets/images/image.png"
        val optionalHeading = ""
        val optionalParagraph = ""
        val listContents = "<li>@Messages('message')</li><li>@Messages('message')</li>"
        val optionalLink = "<br /><a class='button' href='@routes.DashboardController.display(custom)' role='button'>@Messages('message')</a>"
    }

    if(status == "01") {
        //Other variables
    }
    if(status == "04") {
        //Etc...
    }
}

@layout(${pageTitle}) {
        <div class="content__body">
            <div class="hero">
                <div class="${appStatus}">
                    <h1 class="bold-large">@Messages(${title})</h1>
                    <p>
                        ${afterSubTitle}
                    </p>
                    <ol class="appstatus-steps">
                        <li><span class="${step1Status}"><img alt="Complete" title="Complete" src=" + ${image1} + ">@Messages("messages.Received")</span></li>
                        <li><span class="${step2Status}"><img alt="Complete" title="Complete" src=" + ${image2} + ">@Messages("messages.Processing")</span></li>
                        <li><span class="${step3Status}"><img alt="Complete" title="Complete" src=" + ${image3} + ">@Messages("messages.Decision")</span></li>
                    </ol>
                </div>
            </div>

            ${optionalHeading}
            ${optionalParagraph}

            <h2>@Messages("messages.next")</h2>

            <ul class="list list-bullet">
                ${listContents}
            </ul>

            ${optionalLink}
        </div>
    }

Итак, как вы можете видеть, идея состоит в том, что эта страница вызывается с кодом (статусом) и на основе этой строки определяется ряд переменных, которые изменяют способ формирования страницы; контент/css классы/изображения и т. д.

Это не работает (вы можете быть удивлены, узнав!)

Мне действительно непонятно, ПОЧЕМУ это не так. Я думал, что вы обращаетесь к переменным, используя формат ${Variable}, но возможно, вместо этого вы должны использовать формат @Variable.

Даже когда я пытаюсь изменить их на @Variable, у меня все еще возникают проблемы, и я приблизительно понимаю, что это связано с областью действия в Scala/Twirl, и есть «определяющее» ключевое слово, которое можно использовать. Я читал некоторую документацию, но я не понимаю.

Может ли кто-нибудь пролить свет на это?

ИЗМЕНИТЬ

Хорошо, давайте вместо этого просто рассмотрим приведенный ниже код:

@(status: String)(implicit messages: Messages)

@{
    if(status == "00") {
        val myClass = "custom-class-1"
    }
    if (status == "01") {
        val myClass = "custom-class-2"
    }
@layout("page title") {
    <div class="@myClass">This is a div</div>
}

Итак, «все, что я хочу сделать» :) — это иметь возможность определять различные переменные на основе статуса, а затем использовать эти переменные в шаблоне страницы.

Имеет ли это смысл? Я новичок в Scala, поэтому Tuples/Defining сейчас для меня потеряны, но я учусь!


person Sternjobname    schedule 06.01.2017    source источник


Ответы (2)


Вы, кажется, больше привыкли к переменным и областям JavaScript :)

В Scala и Twirl, если вы определяете только переменную (в данном случае это значение, потому что оно неизменяемо) внутри оператора if, значение доступно только внутри блока if.

Одним из решений может быть использование оператора if для возврата кортежа со всеми переменными и использования возможностей операции присваивания, например:

val (myA, myB, myC) = if(something) {
 val a = "a"
 val b = "b"
 val c = "c"

 (a,b,c) // this will return the 3 variables/values because if statements are an expression, and expressions return something
} else {
 val a = "A"
 val b = "B"
 val c = "C"

 (a,b,c)
}

// now you have a,b,c defined in this scope and you can do whatever you need with them

если вы хотите вернуть разные переменные в зависимости от оператора if, у вас будет больше сложностей. решением было бы сделать ненужные переменные null или Option

Дайте мне знать, если вам нужно что-то еще лучше объяснить :)

EDIT: решение для уменьшенного отредактированного примера

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

@(status: String)(implicit messages: Messages)

@{
    val myClass = if(status == "00") {
        "custom-class-1"
    } else if (status == "01") {
        "custom-class-2"
    } else {
      ""
    }

@layout("page title") {
    <div class="@myClass">This is a div</div>
}

Альтернатива с использованием сопоставления с образцом:

замените оператор if/else на:

val myClass = status match {
          case "00" => "custom-class-1"
          case "01" => "custom-class-2"
          case _ => ""
        }

(case _ похоже на "во всех остальных случаях")

person pedrorijo91    schedule 06.01.2017
comment
Благодарю вас! Вы абсолютно правы, JS мне больше по душе! Я отредактировал свой исходный пост с гораздо меньшим фрагментом кода. Не могли бы вы предоставить работающее решение для этого, чтобы я мог увидеть шаблон того, как форматировать мой код? - person Sternjobname; 06.01.2017
comment
только что сделал @SonyaBaled :) - person pedrorijo91; 06.01.2017
comment
Хорошо, я попробовал, но у меня возникла та же проблема, что и раньше: значение «myClass» не найдено. Я думал, что это связано с областью видимости внутри операторов if в Scala, но я могу ошибаться, поскольку я новичок в этом! Любые идеи? - person Sternjobname; 06.01.2017
comment
Вы проверили, какое значение имеет статус? - person pedrorijo91; 06.01.2017
comment
Я точно знаю, что статус содержит «00», поэтому он должен вернуть мне переменную с именем myClass со значением «custom-class-1». Однако переменная myClass не может быть найдена, когда я пытаюсь ее вызвать... - person Sternjobname; 06.01.2017
comment
Хорошо, я понял! Благодаря @pedririjio - это было очень похоже на решение, которое он опубликовал. Я ответил на свой вопрос, чтобы включить код, который я действительно использовал. - person Sternjobname; 08.01.2017

Ответ @pedrorijio почти верен, но фактический код, который в итоге сработал для меня, был таким:

@myClass = @{status match {
  case "00" => "custom-class-1"
  case "01" => "custom-class-2"
}}

Спасибо за помощь!

person Sternjobname    schedule 08.01.2017
comment
О, маленькая ошибка :) у twirl всегда есть какие-то хитрости, надо было попробовать на intellij :p - person pedrorijo91; 08.01.2017
comment
Ах! Это Твирл? Я задавался вопросом, так ли это - без вас я бы не разобрался, так что спасибо! - person Sternjobname; 08.01.2017