I'm trying to dynamically change (if it got clicked) a normal table header (which is a link) to another defined CSS class 'th.hilite'. This link simply sorts this column and the header should got highlighted every time a user sorts the list.
The view where the class in question should be changed, looks like this:
%table#mytable
%thead
%tr
%th= link_to 'Title', mytable_path(:sort => 'title'), :id => 'title_header'
My question is simply: How and where could I dynamically set the class to %th.hilite if the header is clicked?
You can bind it from the view directly:
%th{:class => ("hilite" if #sort == "title")}= link_to 'Movie Title'...
However, you will also have to declare the #sort instance variable in your controller, and set it to either title or release, according to which column you are sorting. (i.e. #sort = params[:sort])
Be careful not to put logic (even conditionals) in your views if you can find a way around it. In order to avoid this common mistake, you need to make good use of the params and session hashes and set appropriate variables in controllers
# In your view
%th{:class => #title_header}= link_to 'Title', my_path(:sort => 'title'), :id => 'title_header'
# In your controller
sort = params[:sort] || session[:sort]
if sort == 'title'
ordering = {:order => :title}
end
BTW as long as values of your param match column name - no need to code each one
def index
#by=params[:by]
#movies = Movie.order(params[:by]).all
end
Javascript or jquery is not required..
The following HAML will work
%th{:class=>('title' == #sortby)?'hilite':""}= link_to 'Movie Title', movies_path(:sort => 'title'), :id => 'title_header'
You should use JavaScript to do this. I think it's good idea for you to use jQuery instead of pure JavaScript. Here are some examples
http://api.jquery.com/click/
http://api.jquery.com/css/
Related
I have used data-confirm attribute with Html::a tags in datagrids and it worked. But now I want to use it with a button like this:
<?php echo Html::button("<span class='icon delete'></span>", [
"class" => "delete",
"title" => Yii::t("app-upload-list", "delete"),
"data-confirm" => Yii::t("yii", "Are you sure you want to delete this item?"),
])
I don't use anchor here because this button doesn't do anything in server-side.
But when I attach a click event to the button, it precedes the confirm box. I can get round it by write the confirm code myself in the click event and use a data-my-confirm (or so) attribute to prevent the double confirm boxes, but it is not so nice. Can I do that with data-confirm?
I had the same problem. Here is Yii's listener (yii.js, line 486):
// handle data-confirm and data-method for clickable and changeable elements
$(document).on('click.yii', pub.clickableSelector, handler)
.on('change.yii', pub.changeableSelector, handler);
It uses Event Delegation
Event delegation allows us to attach a single event listener, to a
parent element, that will fire for all descendants matching a
selector, whether those descendants exist now or are added in the
future.
In this case, the listener is attached to the document node, which is listening for clicks to bubble up from the clicked element. Listeners placed on the clickable elements themselves or anything that is a child of the document node will fire before those on the document node i.e. before Yii's listener.
To ensure Yii's listener fires before your listener you will have to attach your listener to the document node as Yii has done; Listeners on the same node are invoked in the order of their registration.
$(document).on('click', '.delete', yourHandlerFunction);
Note: Event delegation is used when you need a listener for elements that don't necessarily exist when the listener is added or to listen to a single node rather than several. It is usually recommended to use the nearest parent element that exists at the time of adding the listener and that continues to exist while needed. I wouldn't suggest putting listeners on the document node without good reason.
Even if it's an old question I'd like to contribute what I know.
In case you want to use html::button() instead of html::a()
Here is an example
<?php echo Html::button("<span class='icon delete'></span>", [
"class" => "delete",
"title" => Yii::t("app-upload-list", "delete"),
"onclick" => 'if(confirm("Are you sure you want to delete this item?")){
return true;
}else{
return false;
}',
]) ?>
I'm sure it should work.
I think you can find an example of something similar to that in the Yii2 template of a View.
In my view I have the following code:
<?= Html::a('Delete', ['delete'], [
'class' => 'btn btn-danger',
'data' => [
'confirm' => 'Are you sure you want to delete this item?',
'method' => 'post',
],
]) ?>
I have to admit that I have not try to use it with Html::button. But you can try something like this:
<?php echo Html::button("<span class='icon delete'></span>", [
"class" => "delete",
"title" => Yii::t("app-upload-list", "delete"),
"data" => [
'confirm' => 'Are you sure you want to delete this item?',
'method' => 'post',
],
]) ?>
EDIT:
Yes, this way do not Work.
What is recommended is to use a link (Html::a) and style it as you wish.
If you want to submit a Form you should use: Html::submitButton()
If you want to use a button... you can make it work with jQuery as mentioned by Stu here: https://stackoverflow.com/a/12697511/2437857
I am using a Telerik Grid to display data to the client. I have to show priority values first and then display non priority values. When the user group base on priority, the priority values should group first follow by the non priority group. I have a default descending grouping. When the user first access the page, it works fine. However, if the user remove the default grouping and try to group that column again, the non priority values are shown in the first group following by the priority which is the opposite of what I want.
In addition, I tried to do it on the client side using jquery, but the grid variable is always return null.
$(function () {
var grid = $('#Shipping').data('tGrid);
alert(grid) // always return null.
});
Here is the client side code that I am using for that column.
#(Html.Telerik().Grid(Model)
.Name("Shipping")
.DataKeys(Keys =>
{
Keys.Add(c => c.ShippingID);
})
.DataBinding(databinding => databinding.Server())
.Columns(columns =>
{
columns.Bound(p => p.Priority)
.Title("Priority")
.HtmlAttributes(new { style = "text-align:left" })
.Width(50)
.Filterable(false)
.Sortable(true)
.Groupable(true) // I can't tell it group and sort it descending.
.GroupHeaderTemplate(#<text>
.Groupable(grouping => grouping.Groups(gr =>
{
//Here I can tell it that I want to sort it descending
gr.Add("Priority", typeof(Boolean), System.ComponentModel.ListSortDirection.Descending);
}))
Please help me or give me a hint on how to fix this issue?
Adding a client side event fixed the issue, it was the reason why the grid was always showing null value in the JQuery function. The Grouping is still an issue; however, the client agree that they could click on the sort button, and it will sort them properly.
How can I ckick the button or link with a random ID?
Have this button or link a number?
For Example:
#b.link(:number => "1").click
or
#b.button(:number => "1").click
Anyone idea?
If the element is a button, look for some of these static elements:
If the name attribute is known, try: b.button(:name => 'submit').click
If the value (text on the button) is known, try: b.button(:value => 'Submit').click
If the button is an image, you can use a regex on the source: b.button(:src => /destination-url/).click
If the element is a link, look for some of these static elements:
If the name attribute is known, try: b.link(:name => "link").click
If the href attribute is known, try: b.link(:href => "http://example.com").click
If the text of the button is static, b.link(:text => "Text of link here.").click
If these don't work, you can always look to parent elements. Hopefully this helps. I'm glad to elaborate if you provide more information about your specific case.
It works:
#b.link(:index => 1).click
I'm trying to set up a Master/Detail grid using the Grid control from Telerik's Extensions for ASP.NET MVC. My problem is setting up the server template.
The demo I'm following is the first one on this page, except I'm using Razor View Engine.
I have the grid displaying fine. The problem is that I cannot write any sort of a server template that doesn't throw a compiler error - aside from leaving it blank!
#(Html.Telerik().Grid(Model)
.Name("Grid")
.Columns(columns =>
{
columns.Bound(o => o.Date).Format("{0:MM/dd/yyyy}").Width(100);
columns.Bound(o => o.Title).Template(#<text> #item.Title</text>).Sortable(false);
columns.Bound(o => o.Publication).Width(120).Sortable(false);
})
.DetailView(detailView => detailView.Template(e =>
{
//Anything other than this comment will throw a compiler error
}))
.RowAction(row =>
{
// Expand initially the detail view of the first row
if (row.Index == 0)
{
row.DetailRow.Expanded = true;
}
})
.Sortable()
.Scrollable(scrolling => scrolling.Height(494)).Footer(false)
.ClientEvents(events => events.OnRowDataBound("onRowDataBound"))
)
See that comment "anything other than this comment..."? When I replace that with something like #<text> hello</text>, I get a compilation error:
CS1002: ; expected
That doesn't seem to make sense, but I humour myself and put a semicolon in like such #<text> hello</text>;. That gives me this error:
CS0201: Only assignment, call, increment, decrement, and new object expressions can be used as a statement
When I replace that with a portion of the template I really want, namely #<text><b>Slug</b>: #item.Slug</text>, I get the same errors; CS1002 with no semicolon, and CS0201 with a semicolon.
What am I missing here?
There are two ways you can approach this. If you just want to display some simple text and not really integrate any other components it would be the easiest to modify the code you have above to just do this:
.DetailView(detailView => detailView.Template(#<text>test</text>))
As you can see I removed the whole e => { ... } part and just put in #<text></text>.
However, if you want to look into getting more components in your detail view I think it would be better to look at the demo found here. Although the description mentions some WebForms code you don't need to worry, the rest is all in Razor :) It also explains things you have to keep in mind. One of the most important ones is that any components within the DetailTemplate will have to use { ... } as opposed to ( ... ) this is because you want to specifically call .Render(); (using the ( ... ) implicitly calls .Render but at the wrong point for these scenarios) at the end of those components' declaration to make sure they are all rendered correctly.
If i have a formtastic button with a CSS override like this:
-f.buttons do
=f.commit_button :button_html => { :class => 'button positive' }
I am seeing the rendered style as "button positive update" in the browser. How do I get it to only reflect the CSS class that I want to use and dump the "update" class?
No can do, it's part of formtastic
button_html.merge!(:class => [button_html[:class], key].compact.join(' '))
The key in there is the 'create' or 'update' string.