Adding attributes for fields using ejs view helpers - node.js

I am using ejs template rendering
<%- input_field_tag('inputFld', 5) %>
This code generates input field as
<input id="inputFld" value="" type="5" name="inputFld">
Now I want id and name attribute different
ie. id="inputFldID" and name="inputFldName" also I want to add class attribute.
How should I achieve this?

You are probably looking for text_field_tag, because type="5" doesn't make much sense.
You can pass object as third argument to text_field_tag with attributes you want to set.
<%- text_field_tag('inputFld', '5', {id: 'inputFldId', Class: 'some_class'}) %>

Related

Can't render array elements from mongodb document with express-edge templating

I'm following this blog tutorial to learn nodejs backend along with mongodb, it seems a bit outdated(I've had to tweak some stuff to make it work) but also I'm not following it 100%, as I'm making my own front end instead of using a theme and I'm using my own database, which brings to the problem:
While rendering the post lists I want to render inside each post the list of it's tags, which in my database is an array of strings, but it doesnt work. When I try to access the first element of the array only, it return undefined.
This code doesnt render any <li>:
<div class="row" id="lista-posts">
#each(post in posts)
<div class="col-12">
<h4>{{post.titulo}}</h4>
<ul>
#each(tag in post.tags)
<li>{{tag}}</li>
#endeach
</ul>
<div class="post-conteudo">
{{post.conteudo}}
</div>
</div>
#endeach
</div>
This one here render one <li> (as expected) but it's written Undefined:
(...)
<h4>{{post.titulo}}</h4>
<ul>
<li>{{post.tags[0]}}</li>
</ul>
All the other elements like "titulo" and "conteudo" are rendered fine. For context, every post in my db has:
_id: IdObject
titulo: String
tags: Array of Strings
conteudo: String
Turns out it's because I didn't set up the tags array in my mongoose Schema.

Creating a search bar in the permanent layout (app.html.eex)

I am having a surprisingly hard time figuring out how to create a search bar within the app.html.eex template in the Phoenix Framework. Since the area does not change no matter where on the website you are I would prefer it simply just use a HTML get request with the search parameter, so something like this:
<%= button "Search", to: "/search/^search_parameter", method: "get", class: "btn" %>
However I don't know how I can put a variable into the to: string. This code does obviously not work but I imagine something like this:
<div class="search">
<%= text_input :search, :query, placeholder: "Type search query here.." %>
<%= button "Search", to: "/search/^search_query", method: "get", class: "btn" %>
</div>
I pretty much have no clue what the best approach is and I am just trying this out. So any solution is welcome really.
If you want to change the URL of the search form based on user input, you will need to use Javascript. However I think the better approach is to just use a normal form and have your search action accept POST parameters instead.
The route should be
# web/router.ex
post "/search", SearchController, :index
The form should look something like this
# web/templates/layout/app.html.eex
<%= form_for #conn, search_path(#conn, :index), [name: :search], fn f -> %>
<%= text_input f, :query %>
<%= submit "Search" %>
<% end %>
Then you can use the query parameter in the controller
# web/controllers/search_controller.ex
def index(conn, %{"search" => %{"query" => query}}) do
results = # do the actual search using `query`
render conn, "index.html", results: results
end
If you like, you can keep your original route and action in order to support both methods.

How to get values returned by child action method in mvc 5 partial view

I am trying not very successfully to get my head around MVC. My home controller contains an Index method that runs OK, so far so good, but I don't know how to call the ChildAction method Home/TopArticle
Action Method
[ChildActionOnly]
public ActionResult TopArticle()
{
return PartialView(_service.GetTopArticle());
}
In my Index view I have the mark up:
#section featured {
#Html.Partial("_TopItem")
}
_TopItem View
#model IEnumerable<MySite.Models.NewPage>
<section class="featured">
<div id="TopItem">
<div id="TopItemImg">
<a href="http://www.mysite.co.uk/">
<img style="border: 1px solid lightgray" width="320" height="233" style="border:1px solid lightgray;" alt="Model.Title" src="/Img/Model.TopItemImage">
</a>
</div>
<div id="TopContent">
<h2></h2>
<div class="dt">
<div class="dl">
#Html.Label(Model.DatePublished.ToString())
#Html.Label(#Html.Action("TopArticle", "Home", new { // am lost at this point}))
</div>
<div class="tl">
#Html.Label(Model.InfoTags ?? "")
</div>
</div>
</div>
</div>
</section>
The Index view is also using #model IEnumerable and I don't actually know whether that's OK or not. The model itself contains everything needed for both the Index and the _TopItem views, it's just that there will be one record returned for the _TopItem view and many for the Index view. Plus the code that runs in _service.GetTopArticle does some non-query stuff that is relevant only for the top article record.
I need a lie down ... and time to learn this stuff properly.
Firstly, regarding your question about calling the child action from your Index view:
Your featured section is currently calling #Html.Partial which means that it will find the "_TopItem" partial view and render it as an html encoded string in the current view (i.e. your Index view).
You specified that you are trying to call the child action TopArticle() and render the partial view returned as a html string in the view. To do this you would need to use:
#section featured {
#Html.Action("TopArticle", "Home")
}
However, I don't believe this is what you do need as you said that your Index view model contains all of the information for both Index and for the _TopItem partial view (see later).
For more information you should do a google search about the differences of views, partial views and child actions.
To correct the code I would start off by ensuring that the _TopItem partial view is correct. I have identified the following issues with the _TopItem partial view, some of which are beyond the scope of the original question:
The model passed in as an IEnumerable of NewPage but your code does not enumerate over several new page objects, it looks like it should just create the html for a single NewPage model. Therefore, I believe the model declaration should be:
#model MySite.Models.NewPage
The tag contains 2 references to the style attribute rather than 1.
The tag contains the alt attribute of alt="Model.Title" which means that alt="Model.Title" will be written directly as html where I expect you would like alt="#Model.Title" to render the contents of the model in the alt attribute.
Similarily, the tag contains src="/Img/Model.TopItemImage" where I expect this should be src="/Img/#Model.TopItemImage"
All of the label tags appear to be incorrect. For example, #Html.Label(Model.DatePublished.ToString()) - Model.DatePublished.ToString() will return a string and this string will then be attempted to be found on the model and will error as that field name does not exist. Therefore, you probably want to write: #Html.Label("DatePublished") or #Html.Label(m => m.DatePublished). With the second label i'm not sure what your trying to achieve but you may want to look up the appropriate articles.
Once, you have the corrected _TopActicle partial view, you can then return to your Index view to render the partial directly:
#section featured {
#Html.Partial("_TopItem", Model.TopArticle)
}
Note, as you have said that your Index model contains the information to pass to the _TopItem partial view, I have assumed that the Index model contains a property called TopArticle of type NewPage. Regardless, you can pass the model into the partial however you find appropriate through the call to #Html.Partial. If you pass the model through the call to #Html.Partial then you may not need the ChildOnlyAction.

Showing properties from another table - Kentico

we just started with Kentico and are now testing a bit. One thing we're stuck on is showing data in transformations.
We have a custom table like Author. It hase a ID field, FirstName and SurName (both text).
Book is a documenttype and has an ID, Title and a dropdown where we can select an Author.
On a page a have a datalist where i show book with a previewtransformation like this:
<div style="text-align:center;padding: 8px;margin: 4px;border: 1px solid #CCCCCC">
<h2>
<%# Eval("Title") %>
</h2>
Author: <%# Eval("Author.FirstName") %>
</div>
Now we want to show the name of the Author but when using <%# Eval("Author") %> it's showing the ID. We found out that we can use a custom function and return the name, but isn't there another way? Let's say we not only want to show the author's name, but also address, email and so on... Do we really need to create an method for each property we want to show?
Thanks in advance,
Bjorn
No, you can't drill into related tables in this way, because the data of an author is simply not in the data source you are displaying with the data list.
But you don't have to create function for each property of an author you want to display. You may just create a function which will return whole author object, which is in your case CustomTableItem. The function may look like this.
public CustomTableItem GetAuthor(object id)
{
int authorId = ValidationHelper.GetInteger(id, 0);
var pr = new CustomTableItemProvider();
var item = pr.GetItem(authorId, "customtable.author");
return item;
}
Then in a transformation you will use GetValue() method to get the value.
Author: <%# GetAuthor(Eval("AuthorID").GetValue("FirstName")) %>
Be aware of each call of the function will issue a database request, so i would suggest to use some kind of caching. Either output cache for whole page or you may implement some caching mechanism directly inside the function.
The other option you also have is to use CustomQueryRepeater/DataSource and write your own SQL query where you join book data with author data. Then you could use simply <%# Eval("FirstName") %> directly in yout transformation.

Render a variable as HTML in EJS

I am using the Forms library for Node.js (Forms), which will render a form for me on the backend as so:
var signup_form = forms.create({
username: fields.string({required: true})
, password: fields.password({required: true})
, confirm: fields.password({
required: true
, validators: [validators.matchField('password')]
})
, email: fields.email()
});
var signup_form_as_html = signup_form.toHTML();
The final line var signup_var signup_form_as_html = signup_form.toHTML(); creates a block of HTML which looks as such:
<div class="field required"><label for="id_username">Username</label><input type="text" name="username" id="id_username" /></div><div class="field required"><label for="id_password">Password</label><input type="password" name="password" id="id_password" /></div><div class="field required"><label for="id_confirm">Confirm</label><input type="password" name="confirm" id="id_confirm" /></div><div class="field"><label for="id_email">Email</label><input type="text" name="email" id="id_email" /></div>
Basically just a long string of HTML. I then try to render it using EJS and Express using the following code:
res.render('signup.ejs', {
session: loginStatus(req)
, form: signup_form_as_html
});
But on rendering the HTML is simply the string that I posted above, rather than actual HTML (and thus a form as I want). Is there any way to make that string render as actual HTML using EJS? Or will I have to use something like Jade?
With EJS you can have several tags:
<% code %>
... which is code that is evaluated but not printed out.
<%= code %>
... which is code that is evaluated and printed out (escaped).
<%- code %>
... which is code that is evaluated and printed out (not escaped).
Since you want to print your variable and NOT escape it, your code would be the last type (with the <%-). In your case:
<%- my_form_content %>
For more tags, see the full EJS documentation
October 2017 update
The new ejs (v2, v2.5.7) development is happening here: https://github.com/mde/ejs
The old ejs (v0.5.x, 0.8.5, v1.0.0) is available here https://github.com/tj/ejs
Now with ejs you can do even more. You can use:
Escaped output with <%= %> (escape function configurable)
Unescaped raw output with <%- %>
Newline-trim mode ('newline slurping') with -%> ending tag
Whitespace-trim mode (slurp all whitespace) for control flow with <%_ _%>
Control flow with <% %>
So, in your case it is going to be <%- variable %> where variable is something like
var variable = "text here <br> and some more text here";
I had the same issue with rendering the textarea input from from a wysiwyg editor saved as html in my database. The browser will not render it but displayed the html as text. After hours of searching, I found out
<%= data %> escaped data while
<%- data %>left data 'raw'(unescaped) and the browser could now render it.
As per the ejs doc
<% 'Scriptlet' tag, for control-flow, no output
<%_ ‘Whitespace Slurping’ Scriptlet tag, strips all whitespace before it
<%= Outputs the value into the template (HTML escaped)
<%- Outputs the unescaped value into the template
<%# Comment tag, no execution, no output
<%% Outputs a literal '<%'
%> Plain ending tag
-%> Trim-mode ('newline slurp') tag, trims following newline
_%> ‘Whitespace Slurping’ ending tag, removes all whitespace after it

Resources