I am new to angularjs so I may be taking the wrong approach but here is my situation. I have an MVC3 app but I am only using Mvc to serve up a "layout" page and the script and css files. In that view I have a ng-view tag. Here is my routeProvider
$routeProvider.when('/', { templateUrl: '/templates/search.html', controller: 'SearchController' }).
when('/Search', { templateUrl: '/templates/searchResults.html', controller: 'SearchController' });
So initially the search.html template is going to load which is nothing but a form and Search button. The user enters whatever form data they want to search by and click "Search" which is tied to a function $scope.search that gets the form data and call WebApi to get the results. The function returns a promise, and .then I want to assign the results to the $scope and then load the searchResults.html template by calling $location.path("/Search"); The problem is when that is called it reloads the controller and the $scope is wiped out.
I want to do this without using the MVC framework. I know angular takes a new way of thinking and I think my problem lies there. Can anyone guide me to where I should be going with this?
You do not need to call the $location.path("/Search");.
Hide the tag in which you need to show the search results using ng-hide and show it when the promise is executed.
Related
My web page uses Jquery to overload a screen. In this overlay, the user can type some detail and click the submit button.
What I'd like to do is, when the user clicks on submit, the overlay doesn't disappear (as it would do with a page refresh), but a message appears, such as "all done"
The question I have though, is, what is the correct return type? I've gotten myself into a muddle I'm sure.
I tried to make the return type string, and return the string. Sadly, this redirected me to a page with the string value.
I then thought I would need to return a ContentResult() with return Content(myString). The result was the same as returning a string.
I then tried to return void, and simply in my controller use ViewBag.Status ="All done"; This now takes me an empty page.
How can I make the message show "All done" or "Complete" without losing the state? Am I trying to do the impossible without Ajax or similar?
Yes, you are trying to do the impossible. When a controller action gets hit on a synchronous request (e.g. a form submission) you are always going to get a full-page load. That's exactly what a synchronous request is. In effect, the "refresh" has already happened before your action code even runs; the return type of the action is irrelevant. For partial updates, you need an asynchronous request, which means AJAX.
The typical approach to this would be to load in your overlay and then, submit the form from the overlay via AJAX, return a partial view and target a container with jQuery. You'd typically create some kind of generic wrapper for your overlays that will do this for all form posts within any overlay.
Alternatively, you could look at returning JSON and using a JavaScript templating engine like Handlebars to populate the view.
Either way it's a good idea to look at wrapping all of this up in some "generic" JavaScript code that will do the same thing for form posts in all of your overlays; then you can stop worrying about the client-side code and focus on just returning the right thing from your controller actions.
If you want to do that WITHOUT ajax, you will need to return the whole underlaying page again, including the popup in a visible state.
What you (probably) SHOULD do is to use ajax and return a json result. Something like this jQuery solution:
$(document).on('click', '[type="submit"]', function(){
var $form = $(this).closest('form');
$.ajax({
url: $form.action,
type: 'post',
data: $form.serialize(),
success: function(response){
// write success message to user
}
});
});
I am growing increasingly frustrated with Umbraco. I've been working on an Umbraco project for a little while now and I have been unable to figure out how to solve my problem (one of many).
Scenario - I have a content managed page and on this page users can search for things (these things come from an entirely different database to Umbraco). This is fine, I've created a child action which loads the form for search and created the controller method which returns the results. However, each result I need to link to another content managed page (the same content managed page for each result) that takes an ID so I can inject some dynamic data into the content managed page.
Great, I've got a method for handling this request in my surface controller and I can create an Html.ActionLink for each result that when clicked hits my controller action with the id parameter.
Problem - When each link is clicked the url that gets hit is
http://localhost:5645/umbraco/surface/{controllername}/{actionname}/?id={id}
However this request is outside the Umbraco context, so when I try to return any page with the following controller code, I get the following error:
[ActionName("ShowDetials")]
public ActionResult GetProperty(int propertyId)
{
return View("~/Views/TestView.cshtml");
}
Cannot render a macro when UmbracoContext.PageId is null.
So my initial thoughts were to have a separate controller which inherits from Umbraco.Web.Mvc.RenderMvcController and try to handle the request in there, but then this raises other issues like being unable to use #Html.ActionLink to link to a RenderMvcController, I also don't want to have two controllers to handle content from the same section.
The other issues I have is passing custom models to the view.
If anyone can help me, I would be eternally grateful.
For any developer having this same issue the only way I have been able to solve it is by having two controllers. A surface controller to handle the initial rendering of the search form and page and to display the results of the search, then a separate rendermvccontroller to handle clicking on an individual result and displaying a 'details' page.
However, this in my opinion isn't great and I would still greatly appreciate it if anyone has another solution.
if renderpartial in MVC is not like Update panel in ASP.net. than how does it works, and what about the efficiency. I heard that update panel was so inefficient in use. But how does MVC handles postbacks, I need to undestand this before I can dive into MVC
Any suggestions
thank you
ASP.MVC Partial views are just reusable HTML fragments that can be populated by View Models. They don't have any special built in functionality like update panels do.
In general terms, with ASP.MVC you control post backs. In fact, you have to code it all yourself in HTML and JavaScript.
I suggest you start here.
Assuming that you want to update part of your page, the method I use is as follows:
Link a JavaScript function to the event you want to use to update the 'panel'
Make a jQuery AJAX call to an action in your controller
from the controller return a call to the partial view
this will cause the resulting HTML from the partial view to be returned as HTML to your AJAX call
use jQuery to add the HTML to an existing empty div
The AJAX call looks something like
$.ajax({
url: yourControllerAction URL,
data: { CodeTypeID: codeTypeID }, // optional data
type: "POST",
success: function (returnedHtml) {
$("#myDiv").html(htmreturnedHtmll);
}
});
The rest is standard MVC
Hope that helps
I'm new to Asp MVC, and I'm trying to accomplish a little async update (I'm using MVC3 RC2, with Razor, but I can manage with ASPX solutions too).
I have a Master page, which renders a shopping cart box on every page by calling Html.RenderAction("Cart","Shop"). The Cart action of the ShopController calls the database, etc, and outputs the results. This works.
First problem: if I put an ActionLink in this partial view (like Html.ActionLink("Remove")), then even if I call PartialView() from the Remove action, it renders only the shopping cart, and nothing else (in essence, my page disappears).
Second problem: There is a div called "cartContent" inside this partial view. I want to be able to put a link ANYWHERE (not just on the Master page or in the partial view), which when pressed calls a controller Action, and then updates ONLY the cartContent div based on the results. I've tried Ajax.ActionLink but it does the same as Html.ActionLink, even though I imported the Microsoft.MvcAjax js libs.
Also, if I solve the first problem, I want that to be async as well.
What solution do I use? I've tried setting UpdateTargetID to "cartContent", I've tried wrapping the cartContent into an Ajax.BeginForm, nothing. Do I HAVE to use jQuery (which I know nothing of)? Do I serialize some response to JSON, and update the div manually in Javascript? (I'm not really good at JS, I'm coming from the C# side of things)
You put a link wherever you want:
#Html.ActionLink("remove item", "remove", "somecontroller",
new { id = Model.Id }, new { #class = "remove" })
And then in a separate javascript file:
$(function() {
$('.remove').click(function() {
// when the link is clicked
// perform an ajax request:
$.ajax({
url: this.href,
type: 'delete',
success: function(result) {
// when the AJAX call succeed do something with the result
// for example if the controller action returned a partial
// then you could show this partial in some div
$('#someDivId').html(result);
}
});
// don't forget to cancel the default action by returning false
return false;
});
});
Remark: if the div you are updating contains also the link then you might need to use the .live() function or the click event handler will not work the second time because the DOM will be modified:
$('.remove').live('click', function() {
...
});
I have a dropdown list on my master page that needs to postback after being changed. After the postback, whatever page initiated the postback needs to be re-displayed.
My question is where do I handle this? Obviously I do not want to have to modify every Action in my project... My guess is to maybe postback to some other fixed action and have that action redirect back to the page that is the referrer. Am I correct? Any thoughts?
Thanks.
Jason
In Site.Master, I ended up wrapping the dropdown within its own form that posted back to a dedicated controller/action.
<% Using Html.BeginForm("ChangeRole", "Home")%>
<div id="roleSelector">Change Role: <%=Html.DropDownList("Role", DirectCast(ViewData.Item("Roles"), SelectList), New With {.onchange = "this.form.submit();"})%></div>
<% End Using%>
In the controller I used the following code to change the mode and then redirected back to the referring URL.
<AcceptVerbs(HttpVerbs.Post)> _
Public Function ChangeRole() As ActionResult
Me.CurrentUser.SetRole(DirectCast([Enum].Parse(GetType(Models.ApplicationRoles), Me.Request.Item("Role")), Models.ApplicationRoles))
Return Redirect(Request.UrlReferrer.ToString())
End Function
I am unsure if this is the recommended way but I have been unable to think of another solution.
When you post back from the dropdown list change what are you doing? Can you maybe handle this in a jQuery call thus eliminating the need to re-display the page at all?
Calls to Action Methods can be asynchronous as griegs says, as such, you can post whatever information you need from the radio buttons to an action method without needing to reload the page.
If you need to update a part of the page, you can replace it with the contents of a rendered action method. If you use the jQuery ajax methods, you can post specific information to your methods.
For example, something like this:
$(document).ready(function()
{
$("#myRadioButton").change(function()
{
//Post to your action method, with the value of the radio button, function to call on success
$.post('yourActionMethodUrl', $(this).val(), function()
{
//Update some part of the page
});
});
});
This is based on memory, so you may need to check the syntax.