Phoenix Framework:在 JSON 响应中发送呈现的模板
Phoenix Framework: Send rendered template in JSON response
我在 top_navigation.html
中有一个用于我的应用程序顶部导航的模板,其中包含 "Sign in"、"Sign up",并且在登录后,"Sign out" links.
<%= if logged_in?(@conn) do %>
<li><%= link "Sign out", to: session_path(@conn, :delete), method: :delete %></li>
<% else %>
<li><a href="#" class="js-register" data-toggle="modal" data-target=".js-register-modal">Sign up</a></li>
<li><a href="#" class="js-login" data-toggle="modal" data-target=".js-login-modal" >Sign in</a></li>
<% end %>
我通过 AJAX 登录用户,但是一旦他们登录,我想用新呈现的模板(显示 "Sign out" link), 在登录响应中传递回客户端。
有没有办法将呈现的模板作为 JSON 响应的一部分发送?
大致如下:
defmodule MyApp.SessionController do
use MyApp.Web, :controller
def create(conn, %{"user" => user_params}) do
case MyApp.Session.login(user_params, MyApp.Repo) do
{:ok, user} ->
conn
|> put_session(:current_user, user.id)
|> json %{ top_navigation: render("top_navigation.html") }
# ^^^^ this doesn't work ^^^^
:error ->
conn
|> put_status(404)
|> json %{ message: "Unable to sign in." }
end
end
def delete(conn, _) do
conn
|> delete_session(:current_user)
|> put_flash(:info, "Signed out.")
|> redirect(to: "/")
end
end
和 Javascript:
$(".js-login").on("click", e => {
e.preventDefault()
$(".js-login-alert").hide()
})
$("#login").on("submit", e => {
e.preventDefault()
let form = $("#login")
let data = { _csrf_token: $( 'input[name="_csrf_token"]' ).val(),
user: { email: form.find('input[name="email"]' ).val(),
password: form.find('input[name="password"]').val() } }
$.ajax({
type: "POST",
url: "/login",
data: data,
success: e => {
$(".js-top-navigation").html(e.responseJSON["top_navigation"])
// ^^^^^^^^^^^^^^ This is where we swap it out ^^^^^^^^^^^^^^^
$(".js-login-modal").modal("toggle")
},
error: e => {
let alert = $(".js-login-alert")
alert.text(e.responseJSON["message"])
alert.show()
}
})
})
提前致谢!
没错! Phoenix 模板只是它们视图模块上的函数。所以你可以通过调用一个函数来渲染一个模板:
|> json(%{nav: Phoenix.View.render_to_string(MyView, "nav.html", conn: conn)})
我在 top_navigation.html
中有一个用于我的应用程序顶部导航的模板,其中包含 "Sign in"、"Sign up",并且在登录后,"Sign out" links.
<%= if logged_in?(@conn) do %>
<li><%= link "Sign out", to: session_path(@conn, :delete), method: :delete %></li>
<% else %>
<li><a href="#" class="js-register" data-toggle="modal" data-target=".js-register-modal">Sign up</a></li>
<li><a href="#" class="js-login" data-toggle="modal" data-target=".js-login-modal" >Sign in</a></li>
<% end %>
我通过 AJAX 登录用户,但是一旦他们登录,我想用新呈现的模板(显示 "Sign out" link), 在登录响应中传递回客户端。
有没有办法将呈现的模板作为 JSON 响应的一部分发送?
大致如下:
defmodule MyApp.SessionController do
use MyApp.Web, :controller
def create(conn, %{"user" => user_params}) do
case MyApp.Session.login(user_params, MyApp.Repo) do
{:ok, user} ->
conn
|> put_session(:current_user, user.id)
|> json %{ top_navigation: render("top_navigation.html") }
# ^^^^ this doesn't work ^^^^
:error ->
conn
|> put_status(404)
|> json %{ message: "Unable to sign in." }
end
end
def delete(conn, _) do
conn
|> delete_session(:current_user)
|> put_flash(:info, "Signed out.")
|> redirect(to: "/")
end
end
和 Javascript:
$(".js-login").on("click", e => {
e.preventDefault()
$(".js-login-alert").hide()
})
$("#login").on("submit", e => {
e.preventDefault()
let form = $("#login")
let data = { _csrf_token: $( 'input[name="_csrf_token"]' ).val(),
user: { email: form.find('input[name="email"]' ).val(),
password: form.find('input[name="password"]').val() } }
$.ajax({
type: "POST",
url: "/login",
data: data,
success: e => {
$(".js-top-navigation").html(e.responseJSON["top_navigation"])
// ^^^^^^^^^^^^^^ This is where we swap it out ^^^^^^^^^^^^^^^
$(".js-login-modal").modal("toggle")
},
error: e => {
let alert = $(".js-login-alert")
alert.text(e.responseJSON["message"])
alert.show()
}
})
})
提前致谢!
没错! Phoenix 模板只是它们视图模块上的函数。所以你可以通过调用一个函数来渲染一个模板:
|> json(%{nav: Phoenix.View.render_to_string(MyView, "nav.html", conn: conn)})