Can anyone point me in the right direction with implementing the History.js gist with MVC project over at https://github.com/browserstate/history.js
Im just getting to grips with MVC and im considering full Ajax app with Ajax nav or standard nav (urls) with content loaded via Ajax, not sure which way to go but help appreciated.
Im MVC newbie so please forgive me if this is a basic or obvious question
If you are an MVC newbie, you might as well use a library to help you do it.
Backbone does that for you in a very clean way and also supports history through its router.
copy from this link:
Make an MVC Application into a SPA with AJAX and History.js (from Edson_Ferreira)
1.. Let's start with the Layout file. We need to add the following references to our Layout page (_Layout.cshtml):
<script src="~/Scripts/jquery-2.1.0.js "></script>
<script src="~/Scripts/jquery.history.js"></script>
<script src="~/Scripts/jquery.showLoading.js"></script>
2.. Create the Controller(s) and associated Views that we are going to navigate to:
This is how an MVC Controller method that returns a View will look like:
public ActionResult Rating()
{
ViewBag.IsAjaxRequest = Request.IsAjaxRequest();
return View();
}
The reason why we need to specify the dynamic property "ViewBag.IsAjaxRequest = Request.IsAjaxRequest();" is because this information will be used to disable or enable the associated layout with the view being returned.
The '_ViewStart.cshtml' will be responsible for managing this. The file should look like this:
#{
if (ViewContext.ViewBag.IsAjaxRequest == true)
{
Layout = null;
}
else
{
Layout = "~/Views/Shared/_Layout.cshtml";
}
}
This is required to enable the user to type the URL on the address bar and not get a PartialView, but instead, get the expected full page with the layout applied on top of it.
3.. Prepare your links to be managed via AJAX:
On the Anchor Element, we need to add a class that will be used later to bind the 'Click' event using jQuery. Also, we need to add a 'data-ref' attribute so we can store the URL associated with this link.
Because this is an MVC application, we can use the '#Url.Action' helper to assist us in creating the URL; the 1st parameter is the 'View' and the 2nd parameter the 'Controller'.
This is how it should look:
Rating
4.. Prepare a container on which the views will be inserted.
The _Layout.cshtml file should have the following lines of code in it:
<div id="bodyContent">
#RenderBody()
</div>
5.. Create the JavaScript responsible for the AJAX based navigation and history state management:
$(function () {
var contentShell = $('#bodyContent');
var History = window.History, State = History.getState();
$(".ajaxLink").on('click', function (e) {
e.preventDefault();
var url = $(this).data('href');
var title = $(this).data('title');
History.pushState(null, title, url);
});
History.Adapter.bind(window, 'statechange', function () {
State = History.getState();
if (State.url === '') {
return;
}
navigateToURL(State.url);
});
function navigateToURL(url) {
$('#bodyContent').showLoading();
$.ajax({
type: "GET",
url: url,
dataType: "html",
success: function (data, status, xhr) {
contentShell.hideLoading();
$('#bodyContent').hide();
contentShell.html(data);
$('#bodyContent').fadeIn(1000);
},
error: function (xhr, status, error) {
contentShell.hideLoading();
alert("Error loading Page.");
}
});
}
}
6.. Add the reference to this JavaScript file in the _Layout.cshtml file after the views container:
<div id="bodyContent">
#RenderBody()
</div>
#RenderSection("scripts", required: false)
<script src="~/Scripts/App_Scripts/Layout.js"></script>
That's it!
Related
I am trying to learn asp.net. I am making a demo website in which there would be an admin panel. The admin would update the Daily Messages which will get reflected in the main homepage. I am using MVC.
I have created the table in database as
create table DailyMsg(Sno int primary key, msg varchar(max));
This is my controller
public class DailyMsgsController : Controller
{
private amenEntities db = new amenEntities();
// GET: DailyMsgs
public ActionResult Index()
{
return Json(db.DailyMsgs.ToList(),JsonRequestBehavior.AllowGet);
}
}
On running the following URL, I am successfully able to see the data in JSON format.
https://localhost:44329/DailyMsgs
[{"Sno":1,"msg":"Hi!"}]
Now, I am stuck. I know that I would have to add another class for Data Access Layer, but I am confused as how should I parse this data and print it to the main HTML page.
From my research on the internet, I have found out that I might have to use JQuery. So, I wrote the following(with what I could understand from the internet as I am not familiar with JQuery) -
$.ajax({
url: "/DailyMsgs/Index",
type: "GET",
success: function (data) {
$("#div1").html(data);
}
});
This, of course, is not working and I can't see anything on my webpage.
My Homepage.html
<body>
<div id="div1"><h2>Let jQuery AJAX Change This Text</h2></div>
</body>
</html>
<script src="../Scripts/jquery-1.8.0.min.js"></script>
<script src="../Scripts/bootstrap.min.js"></script>
<link href="../Content/bootstrap.css" rel="stylesheet" />
<script src="../JQuery/DailyMsgsJQ.js"></script>
All I want is to read and parse msg from JSON and display it on webpage.
Could you guide me as how should I proceed or is there any other way to achieve the purpose? Thanks a lot!
Try this
$.ajax({
url: "/DailyMsgs/Index",
type: "GET",
success: function (data) {
$.each(data, function (index, element) {
$("#div1").append(element.msg);
});
}
});
If you still have error please get console.log(data); and send for me.
Your <script> tags are outside your <html> tag. That means the scripts are probably not even executed, or not loaded in the correct order. You want jQuery and Bootstrap to be loaded first, so put them in the <head>. Put your custom script just before the closing </body>, so it is loaded last.
Recently I made a small refactor of my application and the paginated tables have stopped working and I think it is because it is not taking the current page that is passed by GET parameters in the URL.
Before the refactor I had a class index.php that included all code HTML along with PHP code, but to optimize and not duplicate code, I started to separate what would be, the navigation menu, the top navbar, and the content in different files .php, so that when I enter a website using this code I load the entire page:
$(function () {
$.get("../navbar.php", function (data) {
$("#navbar-menu").append(data);
});
$.get("../menu.php", function (data) {
$("#sidebar-wrapper").append(data);
});
$.get("./content.php", function (data) {
$("#divPersonal").append(data);
});
});
When I enter for example one of these pages where I have a table with pagination and type links:
http://localhost/app/modules/users/index.php?page=2
When I reload the index.php and it loads with javascript the "content.php" where I have the PHP call of "getUsers()", it should take the URL and the "page" parameter but it is not doing it, and it seems that it is due to the way my index.php is being mounted. I can not find an optimal solution to solve this problem. I take the parameters directly when I call the function with an if:
if (empty($_GET['page'])) {
$firstPage = 0;
$actualPage = 1;
} else {
$actualPage = $_GET["page"];
$firstPage = ($actualPage - 1) * $SIZE;
}
If anyone can help me, thank you.
Name the pages with them titles and make like this to switch between pages:
if(isset($_POST["page"]))
{
switch ($_POST["page"]) {
case "login":
include '/folder/page.php';
}
}
Am playing with Framework7 to do hybrid mobile app development. I have three tabs (bottom fixed), which are Home, Contacts and Settings/Profile
My app.js file looks somewhat like this:
var $$ = Dom7;
var app = new Framework7({
//.....
data: function () {
return {
user_profile : ''
}
},
on: {
tabShow( tab ) //-- when a bottom tab is clicked
{
if( $$(tab).attr('id') == 'view-settings' )
{
//.. do ajax call and get the response data in "resp"
app.data.user_profile = resp.response.profile; //setting the info to app's data
}
}
},
routes: routes
});
var settingsView = app.views.create('#view-settings', {
url: '/settings/'
});
And in routes.js:
routes = [
{
path: '/',
url: './index.html',
},
{
path: '/contacts/',
componentUrl: './pages/contacts.html',
},
{
path: '/settings/',
componentUrl: './pages/settings.html',
}
];
This Contacts page contains static content. For the Home page, am doing the AJAX API call during the deviceready state. Because am setting up some headers for authentication and stuff(for all the AJAX api calls) in there.
The problem am facing is, am unable to display the content in Settings page. It is always empty!
Am using this in that template page:
<div class="item-title item-label">Full Name - {{$root.user_profile.full_name}}</div>
I want to compile that template only when clicking the respective tab button.
Maybe that's the problem.
Any suggestions?
After going through the documentations again and again, I got another way to do this.
So, during the tabShow event, I check whether the user is accessing the Settings/Profile tab. If so, I check whether an object in app.data (eg: app.data.user_profile is empty or not(am storing the profile details there). If empty, I would do an AJAX API call to get the profile details. When the profile details is obtained, I would use app.form.fillFromData() method to fill the form. Documentation here: https://framework7.io/docs/form.html#form-data-app-methods
Make sure to name the form as well as the input elements in that form, and the same name should be use in the object(key name) when calling the fillFromData() function.
And one more thing, for the routes, /settings/ path, I used url instead of the componentUrl property to pass the url of the page.
This may not be the best solution, but am still learning. And it seems to have solved by current problem.
Thank you
Scenario:
I have written an MVC wizard that automatically uses ajax if javascript is enabled in the browser. Each step of the wizard is a PartialView (I'm using ASP.NET MVC 3).
All works fine.
The problem is refreshing the page if, for example, the user's status changes as a result of how she fills in the wizard. EG, if the wizard logs the user in, or registers them. As the wizard 'moves' from step to step by getting Partial Views via AJAX, the page doesn't get refreshed to reflect the change in the user's status (eg, an anonymous user is now registered).
What I want to do:
Essentially, when I need a full page refresh, I need to AUTOMATICALLY run the following on the client AFTER delivering the Partial View corresponding to the current step of the wizard via AJAX:
location.reload();
The Problem:
As the DOM has been modified via AJAX, I don't know how to make my javascript (location.reload();) run WITHOUT user intervention (eg, clicking a button).
Any suggestions? I have been off work for a while and am struggling to get back up to speed.
For now, I have solved my problem using the code in the following article:
Redirecting after AJAX call, when using ASP.NET MVC
I like the approach discussed in the article because it results in reusable code, in a very MVC way - I already have a base controller (AjaxController.cs) where I encapsulate all my AJAX aware code and this is a nice addition to it.
However, there are two issues with this approach:
I have to redirect away from my wizard, so it only works for the final step of the wizard. If the user's status changes half way through the wizard, I am still jiggered.
I would still like to know how to refresh my page after an AJAX call, rather than just redirecting like this.
So if anyone has the answer, I will gladly give them the biscuit.
I am not quite sure how your ajax calls are structured, but if you are using the MVC Ajax helper you can just call location.reload(); in the OnComplete method, like so:
#using (Ajax.BeginForm(new AjaxOptions{OnComplete = "javascriptfunction"}))
{
//Data and submit button
}
<script>
function javascriptfunction(){
location.reload();
}
</script>
// C# code
public ActionResult Foo(Bar bar)
{
// code here
return Json(new
{
Success = true,
Value = this.RenderPartialViewToString("PartialViewName", bar),
Callback = "window.location.href = 'http://yourdomainurl.com/';"
});
}
// jQuery Ajax
$.ajax({
type: "POST",
url: "/urlWhereToPost",
data: ("form#id").serialize(),
dataType: 'json',
async: false,
beforeSend: function() {
// some instruction
},
error: function(e) {
alert(e.responseText);
},
success: function(data) {
if (data.Success) {
if (data.Callback != null) {
if (data.Callback.length > 0) {
jQuery.globalEval(data.Callback);
}
}
}
else {
// do something
}
}
});
I would like to have a page that would contain:
hyperlik "Add new country".
After clicking this link by user, dropdown list with names of countries should appear. However this hyperlink should stay on this page. When user click this hyperlink once again, second dropdown list with exactly the same names should appear. This should be repeat as long as user clicks hyperlink.
It is important that this page shouldn't be reloaded.
Does anyone has any idea how can it be made?
The typical way to achieve this is to have your Add new country link trigger an ajax call out to a page you create which will provide the data for your list.
The preferred method these days seems to be having that page you call build up a JSON response, then your callback on the ajax method where you called it can populate that data into a drop down.
The page you call from AJAX could be something simple like this:
protected override void Render(HtmlTextWriter writer)
{
Dictionary<string, int> myStuff = new Dictionary<string, int>();
myStuff.Add("country1", 1);
myStuff.Add("country1", 2);
JavaScriptSerializer jss = new JavaScriptSerializer();
Response.Write(jss.Serialize(myStuff.ToList()));
Response.ContentType = "application/json";
}
Use this jQuery on your main page:
<script type="text/javascript">
$(document).ready(function () {
$("#btn").click(function () {
getCountries();
});
});
function getCountries() {
$.ajax({
url: "ApiPage.aspx",
dataType: "json",
success: function (data) {
for (var i in data) {
$("#myDropDown").append($('<option></option>').val(data[i].Value).html(data[i].Key));
}
}
});
}
</script>
Tested and working. (in a simplified example) I did have to convert from Dictionary to List for the json serializer to make it an array as desired. See the updated Serialize call. There is also some validation, e.g. did the ajax call return real data?, that would need added to a real life implementation.
It looks like you are doing it a least approximately right.
in the HTML if you have some tag that surrounds the area you want the drop down box to then it is simple.
for example:
in HTML:
Add new country
<div id="dropdownarea"></div>
in javascript:
function addDD(){
document.dropdownarea.innerHTML += "HTML code for the drop down that you want";
}