Display different forms on Index page depending upon link clicked in ASP.NET MVC - asp.net-mvc

I have a menu control on Index page rendered as <% Html.RenderPartial("MenuUserControl"); %> where MenuUserControl is something like
<li><%= Html.ActionLink("Link1","Index") %></li>
<li><%= Html.ActionLink("Link2", "Index")%></li>
<li><%= Html.ActionLink("Link3", "Index")%></li>
Now I wan to load three different form in Index page itself onclick of these links, with first form being loaded on Page load. How can I do this. Any help is appreciated.

If you need to pass information about links to RenderPartial
<% Html.RenderPartial("MenuUserControl", new[]{"link", "link"}); %>
however it's better to pass a custom model (class object) rather than array of strings.
Use Ajax.ActionLink to load form without page reload.
To load first form either do this in the Index page itself (add HTML tags or call RenderPartial to render form, or use RenderAction), or add script to the menu partial like this
<script type="text/javascript">
$(function(){ $("a").eq(0).click(); }
</script>
This requires jQuery, though.
If you don't know what I'm talking about then you better prepare to learn a lot.

You will need some sort of JavaScript library like jQuery to do this, the rest is imagination:
-You can pre-load the 3 forms on pageload and then hide the last two on DOM ready (PageLoad). i ll wrap this in div just for convenience.
<script type="text/javascript">
$(document).ready(function () { //This is like DOM ready
//here we hide the the last 2 forms
$('#div_id_form2').hide();
$('#div_id_form3').hide();
//Next set the events for the links (on click show form)
//on link 2 click
$('#link2').click(function(){
//show the second form
$('#div_id_form2').show();
});
//on link 3 click
$('#link3').click(function(){
//show the third form
$('#div_id_form3').show();
});
});
</script>
The other option is go the Ajax way but requires more code and knowledge in jQuery.
If you are interested refer to http://docs.jquery.com/ thats the API reference for jQuery.
If you are moving to MVC, I recomend you to learn any JavaScript library to help you with this kind of behaviors that some call DHMTL (Dynamic HTML).

First do the Non Ajax Version.
Have 1 page Index with 3 partials in it. Each partial has only the html for the form to display in it.
In your actions set the ViewModel (here Action Link1)
model.IsForm1Visible = true;
In your View use the model to display partials
<div id="linkContainer">
<% if(Model.IsForm1Visible){%>
<%= Html.RenderPartial("Form1")%>
<%}%>
<% if(Model.IsForm2Visible){%>
<%= Html.RenderPartial("Form2")%>
<%}%>
<% if(Model.IsForm3Visible){%>
<%= Html.RenderPartial("Form3")%>
<%}%>
</div>
If you need Ajax you can continue from there.

Related

render (partial) and scope between elements

I have a checkout popup I would like to share between different pages (event, video meeting ...), so I thunk creating a shaded element /views/shared/_checkout.html.erb, and insert <%= render "shared/checkout" %> in my pages.
Uncaught ReferenceError: popup_payment is not defined
All the html and javascript is this shared page.
I just can't understand why from my pages (event, video ...) I can not call the javascript from this shared component.
the html and the javascript is present when I check the source. I was excepting that render / render partial was acting some code injection, am I wrong ?
How could I preserve the DRY - Don't repeat Yourself - in ERB ?
And have the elements / javascript communicate betweek page and included javascript ?
Here is some pseudo code example :
pageA.html.erb
<%= link_to image_tag('pinandchip.png', size: '18x18'), '#', onclick: 'popup_payment();', class: "btn flat" %>
...
view/shared/_popup.html.erb
<script>
function popup_payment() {
}
</script>
You could try adding the class payment-popup-button to your button and create a new file in app/assets/javascripts/shared called popup.js.
In that file you can do something like:
$(document).ready(function(){
$('payment-popup-button').click(function(e){
e.preventDefault();
$('#popup_payment_div').show();
});
});
This assumes that you're using jQuery, and that you've already rendered the popup code somewhere on the page, but it's hidden.
If you need to render a fresh form every time or populate the form with dynamic data you'll probably have to create controller actions that respond_to and render js.erb to get you the right markup.
It's hard to say exactly without seeing more code.
Are you ensure that your javascript function is loaded in all pages?
On this question answer how to have global javascript functions on rails projects.
i found a solution with this gem :
https://github.com/komposable/komponent
it fulfill my needs : create external components

Display selection of index in a partial

I've been trying to solve the following challenge all day without any luck.
When going through forum posts I came across jQuery and AJAX which are both new concepts to me and which I'd rather skip for now, if possible.
I've got a partial, "navbar-left", which shows a list of all bank accounts in my model Account.
When the user clicks on one of the items in the list, all transactions of that account should be shown in the same page at the right. The partial below links to a new page which is not how I'd like it.
The navbar-partial:
<ul class="nav nav-pills nav-stacked">
<% #accounts.each do |account| %>
<li role="presentation"><%= link_to account.account_holder, account_mutations_path(account.id) %></li>
<% end %>
</ul>
Any tips on how to get this fixed is much appreciated!
The page with the navbar at the left
The mutations in a separate page instead of a partial
Either you're sending viewers to a new page, or dynamically loading content within their current page.
If the latter, then the only solution is AJAX.
Luckily, Ruby on Rails makes transitioning from one to the other very easy.
Here is a gist of how it works:
<%= link_to account.account_holder, account_mutations_path(account.id), remote: true %>
This was pointing back to some page previously (e.g. action.html.erb).
Because of remote: true, it's going to be sending JS directly to the browser instead of a new HTML page (e.g. action.js.erb in the same view folder and same action name).
Here we can control the behavior we want by rendering a partial using ERB and using JS to change the HTML content of some part of the page:
// action.js.erb
$('#some_element').html('<%= j render "partial" %>')
Which will insert the HTML of the partial directly into the JQuery that changes the content dynamically.
Where j is a shorthand for escape_javascript.
Without escaping, the Ruby output is interpreted as file output and newlines would break your JS.
Example JS output without escaping:
// Bad
$('#some_element').html('<span>Content</span>
<span>More Content</span>')
Example with escaping:
// Good
$('#some_element').html('<span>Content</span>\n<span>More Content</span>')
http://guides.rubyonrails.org/working_with_javascript_in_rails.html
https://launchschool.com/blog/the-detailed-guide-on-how-ajax-works-with-ruby-on-rails
There are more great examples online and even Railscasts.
Really AJAX is the best way to do this, and it's not as complicated as you might think. But if you really want to skip AJAX then your best approach is probably to load ALL transactions for all accounts, in different div's and then show or hide them based on which is clicked.
For a rudimentary introduction to this look at javascript tabs... you click on a tab, the appropriate information is shown.
http://www.w3schools.com/howto/howto_js_tabs.asp
You can do this very simply without ajax. The big difference would be - it's not the same page. One page would be the account#index (as you have now), the other page is the account#show page.
For the show page, use a very similar view as the index page, the left side would include the partial with one of the account li class="active" to highlight the account you are currently on. For the right side of the page, render the account mutations list items.

How can I change the .erb rendered in a <div> with a button click in RoR?

I am a newbie to RoR, and I was using Chartkick with HighCharts to display some graphs from my sqlite database. The graphs are daily and weekly, so I have two .erb-s with the query for each of them, and I want the index.html.erb dynamically change between them in my with a click of a button.
This is the code from the daily_graph.erb:
<div><%= line_graph Product.where(date_time: "2014-03-03 00:00:00".."2014-03-03 23:45:00").group(:date_time).sum(:value) %></div>
This is the code from the weekly_graph.erb:
<div><%= line_graph Product.where(date_time: "2014-03-03 00:00:00".."2014-03-09 23:45:00").group(:date_time).sum(:value) %></div>
How can I manipulate with these views in my index.erb, so when I click the WEEK button, daily_graph will disappear, showing weekly_graph, and the contrary.
Two things:
1) Keep the views dumb. Do the SQL query inside the controller, and set it as a variable that the view accesses. So, it would be:
# Inside your controller
def index
#daily_products = Product.where(date_time: "2014-03-03 00:00:00".."2014-03-03 23:45:00").group(:date_time).sum(:value)
#weekly_products = Product.where(date_time: "2014-03-03 00:00:00".."2014-03-09 23:45:00").group(:date_time).sum(:value)
end
Then your view would just be:
<div class="graph"><%= line_graph #weekly_products %></div>
<div class="graph hidden"><%= line_graph #daily_products %></div>
2) the .erb file is used for server-side templating, so switching back and forth would need to happen on the client side. You can have both graphs on the page and use an event handler to disable / show the respective graphs when the button is pushed.
On the index page, lets say you have <button id="flipGraphs">Change</button>
Using jQuery, you can do:
$(function(){ // If you are not familiar with jQuery, this will run when the page is loaded and ready
$('#flipGraphs').click(function(){
$('.graph').toggle(); // toggles all of the divs as hidden / shown
});
});
Also, add this to your application.css file:
.hidden{
display: none;
}
You want to turn those ERB views into partials... then you can make a new controller action that renders the particular partial your interested in, and you can fetch that controller action with jQuery ajax calls... see: Rails: Rendering Partials through Ajax for more examples
Also conventionally you would not execute model finder methods in the view ... set controller instance variables and reference them instead... this will lead directly to an overall more DRY result.

Jquery Mobile Javascript not working on ajax load

Have the following markup in my html page to toggle a search bar based on if a search icon is clicked:
<a id="searchIcon" href="/"></a>
<div id="searchWrapOuter" style="display:none;">
<div id="searchWrapInner">
<div id="formContainer">
<form id="searchForm" action="#">
<div>
<input type="search" name="search-mini" id="search-mini" value="" data-mini="true" />
</div>
</form>
</div>
</div>
</div>
Width the following javascipt/jquery:
$(function() {
$(document).on("click", "#searchIcon", function () {
var searchWrapper = $("#searchWrapOuter");
$(searchWrapper).slideToggle();
return false;
});
});
This code works as expected on a page load direct off a Url. When coming into the page off a link which is Ajax loaded, loads the contents of the page into the DOM, and the DOM ready handler only executes for the first page.
I have read about using the
$(document).on('pageinit'), not $(document).ready()/$(function()
I still haven't been able to get this to work when coming in off an ajax link however. What would be the correct way to implement these events to get the code to work coming in from an Ajax link?
Thanks,
Most likely it is because you are using IDs instead of classes. jQuery Mobile doesn't work well with IDs because it caches pages into the DOM so if you open a page, close it, then go back to the page, you might have your page twice inside the DOM (one visible, one hidden/cached). So when you do $("#searchWrapOuter") you don't know which element you are actually dealing with (in your case, probably the hidden one).
The solution is to change your IDs to classes. This is not very intuitive but I found that is the best way to work with jQuery Mobile.
Also note this comment in the doc which might also be relevant to you:
The id attribute of all your elements must be not only unique on a given page, but also unique across the pages in a site. This is because jQuery Mobile's single-page navigation model allows many different "pages" to be present in the DOM at the same time. This also applies when using a multi-page template, since all "pages" on the template are loaded at once.
http://jquerymobile.com/demos/1.2.0/docs/pages/page-anatomy.html
You can manually adjust delay time to 500ms and 1s.
$(searchWrapper).delay(1000).slideToggle();
My issue is that the page id was below the pages tags. So once I moved the page div above it, the javascript was included in the ajax page load. Previous to this

Using RenderPartial twice for same mvc view control in one page, get problems

I'm using same partial view in create.aspx view page twice, part of my code is:
<%Html.RenderPartial("LocationVerifyControl"); %>
<%Html.RenderPartial("LocationVerifyControl"); %>
In the mvc view user controls, it had a button and test code for it:
$('#btnVerify').click(function() { alert("clicked by btnVerify");}
I watched the warning dialog pop up twice when clicked the button, the main view page had contents with same ids. How to solve this kind of problems? To prevent same ids in main view page, put my using html ids in the view data and pass them to partial view?
If I understand your question correctly, you are looking to add unique functionality to two different buttons with the same id.
It's not really valid to have more than one element with the same id. If there will be multiple you should just make it a class. You might want to first run your markup through W3C Validation.
Second you can do this by wrapping the partials in a div or whatever element you like. Something like this:
<div id="first">
<% Html.RenderPartial("LocationVerifyControl"); %>
</div>
<div id="second">
<% Html.RenderPartial("LocationVerifyControl"); %>
</div>
Then your script section can reference the buttons independently.
$('#first #btnVerify').click(function () {
alert('first button click');
});
$('#second #btnVerify').click(function () {
alert('second button click');
});
Notice that I'm just saying to find the id=first then find a id=btnVerify within the id=first.

Resources