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.
Related
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'}) %>
I'm trying to figure out how to search multiple models with Ransack. The goal is to have the search form in my shared header. I'm using a combination of their documentation, an old rails-cast, SO questions, and some code a friend shared with me. Right now I think it works, although I'm not sure because I can't get the results to show on my index page.
First, I created a search controller:
class SearchController < ApplicationController
def index
q = params[:q]
#items = Item.search(name_cont: q).result
#booths = Booth.search(name_cont: q).result
#users = User.search(name_cont: q).result
end
end
Next, I put this code in the header partial (views/layouts/_header.html.erb):
<%= form_tag search_path, method: :get do %>
<%= text_field_tag :q, nil %>
<% end %>
I added a route:
get "search" => "search#index"
My index.html.erb for the Search controller is empty and I suspect that is the problem, but I'm not sure what to place there. When I try something like:
<%= #items %>
<%= #users %>
<%= #booths %>
This is the output I get when I execute a search:
#<Item::ActiveRecord_Relation:0x007fee61a1ba10> #<User::ActiveRecord_Relation:0x007fee61a32d28> #<Booth::ActiveRecord_Relation:0x007fee61a20790>
Can someone please guide me on what the solution might be? I'm not sure if it's an index view problem, routing problem, or something else. On all of the tutorials the search field and results are only for one model so I'm a little confused on how to pull this off across multiple models.
Thanks!
The output you are getting is correct. Each of those variables contains an ActiveRecord_Relation object which can be treated like an array. Normally you'd do something like:
<% #items.each do |item| %>
<%= item.name %> # or whatever
<% end %>
<% #users.each do |user| %>
# and so on
Alternatively, you could combine your results #results = #items + #booths + #users and then:
<% #results.each do |result| %>
# display the result
<% end %>
I am trying to implement simple search form for users to look up other users.. I have been looking around the web for quite some time, but lot of the resources seem to be outdated, either for rails 3 or retired gems...
Can anyone pin point me to a recent rails 4 resources for simple search or show me the skeleton code to start? thank you in advance!
https://github.com/jhund/filterrific
scope :search_query, lambda { |query|
return nil if query.blank?
terms = query.to_s.downcase.split(/\s+/)
# replace "*" with "%" for wildcard searches,
# append '%', remove duplicate '%'s
terms = terms.map { |e|
(e.gsub('*', '%') + '%').gsub(/%+/, '%')
}
# configure number of OR conditions for provision
# of interpolation arguments. Adjust this if you
# change the number of OR conditions.
num_or_conds = 2
sql = "(LOWER(foo.first_name) LIKE ? OR LOWER(foo.last_name LIKE ?)"
where(
terms.map { |term| sql }.join(' AND '), *terms.map { |e| [e] * num_or_conds }.flatten
)
}
That would be a simple example of searching a user by either first_name or last_name.
Filterrific is quite good, but can be heavy on the back side when it does the query if you have many records.
For a very simple search on Users username you can do in your view :
<%= form_tag users_path, :method => 'get', :id => 'users_search' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
In your User model you must define a 'search' method :
#users_controller.rb
def self.search(user_name)
if user_name
user_name.downcase!
where('LOWER(name) LIKE ?', "%#{user_name}%")
else
all
end
end
and finally in your controller you can call this method :
def index
#users = User.search(params[:search])
end
The route can be defined as a GET like your default route for the page :
#routes.rb
resources :users
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.
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