iron-ajax to only make request if url parameter exists - ajax

This iron-ajax should make a request only if an url-parameter named itemId exists. And that parameter should also be added to the request:
<iron-ajax auto="false"
url="/api/item"
params='{"id":"{{app.itemId}}"}'
handle-as="json"
on-response="loadItem"
debounce-duration="1000">
</iron-ajax>
With this example the (wrong) generated url is:
http://localhost:8080/api/item?id=%7B%7Bapp.childId%7D%7D
The route to display the element is set up like this:
page("/polymer/item", function() {
app.route = "itemform";
});
page("/polymer/item/:itemId", function(data) {
app.route = "itemform";
app.params = data.params;
});

The first problem is that you have a fundamental issue with how you provide the itemId in the parameter.
It cannot be within the string of the 'params' attribute. The best way to resolve that is to use a function: (this assumes the itemId is a value within the "app" template)
<template is="dom-bind" id="app">
<iron-ajax id="itemAPI"
url="/api/item"
params='{{createIdParam(itemId)}}'
handle-as="json"
on-response="loadItem"
debounce-duration="1000">
</iron-ajax>
</template>
<script>
app.createIdParam = function(id) { return {id:id}; }
</script>
The next issue is that it seems you do not want the iron-ajax to auto-request when the URL is set. Since the string "false" is truthy (weird, sure but true) it will make the request. Simply do not include the auto parameter, then use the following code (using the ajax changes my example above) to initiate the ajax request.
if (app.itemId)
document.querySelector("#itemAPI").generateRequest();
Hope the answers more than your original question.

At the end of the day, I added the logic to make the request or not, to my routing setup.
There are two different routes anyway, one without param, and one with.
I just added the generateRequest() call to the route WITH parameter.

Related

Ajax Thymeleaf Springboot

I'm trying to use ajax with thymeleaf. I designed a simple html page with two input field. I would like to use addEventHandler for the value of first input text, then I want to send it to controller and make calculation, after that I need to write it in same html form in the second field which returns from controller.
For example:
first input text value -> controller (make calculation) -> (write value) in second input text.
My html page is
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<link rel='stylesheet prefetch' href='http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css'>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<input type="text" name="Thing" value=""/>
<script th:inline="javascript">
window.onload = function () {
/* event listener */
document.getElementsByName("Thing")[0].addEventListener('change', doThing);
/* function */
function doThing() {
var url = '#{/testurl}';
$("#fill").load(url);
alert('Horray! Someone wrote "' + this.value + '"!');
}
}
</script>
<!-- Results block -->
<div id="fill">
<p th:text="${responseMsg}"/></div>
</div>
</body>
</html>
My controller
#RequestMapping(value = "/testurl", method = RequestMethod.GET)
public String test(Model model) {
model.addAttribute("responseMsg","calcualted value")
return "test";
}
However I cannot call controller from ajax. Could you help me?
There are a few issues with your code. First of all, it looks like you're using the same template for both the initial loading of the application, and returning the calculated result.
You should split these two into different calls if you're using AJAX, since one of the goals of AJAX is that you don't need to reload an entire page for one change.
If you need to return a simple value, you should use a separate request method like this:
#GetMapping("/calculation")
#ResponseBody
public int multiply(#RequestParam int input) {
return input * 2; // The calculation
}
What's important to notice here is that I'm using #ResponseBody and that I'm sending the input to this method as a #RequestParam.
Since you will be returning the calculated value directly, you don't need the Model, nor the responseMsg. So you can remove that from your original request mapping.
You can also remove it from your <div id="fill">, since the goal of your code is to use AJAX to fill this element and not to use Thymeleaf. So you can just have an empty element:
<div id="fill">
</div>
Now, there are also a few issues with your Thymeleaf page. As far as I know, '#{/testurl}' is not the valid syntax for providing URLs. The proper syntax would be to use square brackets:
var url = [[#{/calculation}]];
You also have to make sure you change the url to point to the new request mapping. Additionally, this doesn't look as beautiful since it isn't valid JavaScript, the alternative way to write this is:
var url = /*[[ #{/calculation} ]]*/ null;
Now, your script has also a few issues. Since you're using $().load() you must make sure that you have jQuery loaded somewhere (this looks like jQuery syntax so I'm assuming you want to use jQuery).
You also have to send your input parameter somehow. To do that, you can use the event object that will be passed to the doThing() function, for example:
function doThing(evt) {
var url = [[#{/calculation}]];
$("#fill").load(url + '?input=' + evt.target.value);
alert('Horray! Someone wrote "' + this.value + '"!');
}
As you can see, I'm also adding the ?input=, which will allow you to send the passed value to the AJAX call.
Finally, using $().load() isn't the best way to work with AJAX calls unless you try to load partial HTML templates asynchronously. If you just want to load a value, you could use the following code in stead:
$.get({
url: /*[[ #{/calculation} ]]*/ null,
data: { input: evt.target.value }
}).then(function(result) {
$('#fill').text(result);
});
Be aware that $.get() can be cached by browsers (the same applies to $().load() though). So if the same input parameter can lead to different results, you want to use different HTTP methods (POST for example).

whats wrong in this jquery ajax method call?

I'm trying to pass the value of a text box to a action method through jquery ajax method. The action method will return a bool value, based on which I need to show a message in my view. I'm trying this:
<script type="text/javascript">
$(document).ready(function () {
$('#UserName').blur(function () {
var name = this.value;
$.get(#Url.Action("CheckUserName"),{UserName:name},function(data,status){
if(data==true)
{
}
else
{
}
}););
})
});
</script>
Now the problem is, only the if statement is executing! I have checked my action method, its returning true & false accordingly. I need to know what the callback function's parameter "data" is supposed to do? Will it hold the data returned from the action method?
You're missing quotes around url.
$.get('#Url.Action("CheckUserName")',{UserName:name},function(data,status){
Remember, that you need to render a proper javascript, and strings in js need to be enclosed with quotes.
In JS code, you need to put 3 equal sign in if statement. thats it!

Relative URL inside $ajax with asp.net mvc 3

I know one can use this function
#Url.Action("MyInfo", "Home")
to avoid the hardcoding of urls, but my $.ajax calls are in a separate .js file. Would the above still work?
From my knowledge, the #Url.Action will only work inside the Razor file. But considering that we are advised to use non-obtrusive JS, I am not quite sure how I would use the #Url.Action.
Please advise.
Would the above still work?
No.
From my knowledge, the #Url.Action will only work inside the Razor file
Your knowledge is correct.
But considering that we are advised to use non-obtrusive JS, I am not
quite sure how I would use the #Url.Action.
You could use HTML5 data-* attributes on some DOM element that you are unobtrusively enhancing (unless this element is already a <form> or an anchor in which case it already contains an url):
<div id="foo" data-url="#Url.Action("foo")">Hello</div>
and then in your separate javascript file:
$(function() {
$('#foo').click(function() {
var url = $(this).data('url');
// TODO: do something with the url
});
});
Add a function parameter for the relative paths. E.g., in your View:
<script type="text/javascript">
var path = "#Url.Action("ActionName", "ControllerName")";
someAjaxMethod(path)
</script>
and in your external js file:
function someAjaxMethod(path)
{
var data = {};
$.ajax(path, data)
}

MVC3 routes interfering with JS paths

I have the following route defined:
routes.MapRoute(name: "StateResults", url: "{state}/{searchTerm}", defaults: new { controller = "Results", action = "SearchState" });
In one of my shared chtml files I have the following defined:
<script src="#Url.Content("Scripts/jquery-1.5.1.js")" type="text/javascript"></script>
I understand why the JS is not getting loaded, but how do I get around this? I get around this?
Thanks.
You can ignore routes for JS
IgnoreRoute("{file}.js");
As an alternative method you can use the constraint parameter to avoid files ending with js
routes.MapRoute("StateResults", "{state}/{searchTerm}",
new { controller = "Results", action = "SearchState" },
new { searchTerm = #".*?([^js])$" }); // regex not tested
RouteCollectionExtensions.MapRoute Method (RouteCollection, String, String, Object, Object) from MSDN
constraints
Type: System.Object
A set of expressions that specify values for the url parameter.
you need to set up the routes that it ignores .js files.
a good description is found here:
http://weblogs.asp.net/rashid/archive/2009/04/03/asp-net-mvc-best-practices-part-2.aspx
something like this will do the trick:
routes.IgnoreRoute("{file}.js");

How do I get the correct URL for an MVC action when using Jquery/AJAX?

So I have my first MVC2 site that I'm working on and naturally I'd like to throw some AJAX in there. The problem is, is that I don't know how to get the URL for the action when passing in a URL parameter. Let me explain. The examples I've seen so far show the developer passing in strings like '/MyController/MyAction'. That's great, except if your controllers are not in the root directory of your website (as is the case in my situation). I could always use relative URLs like 'MyAction' except if the URL contains parameters that doesn't work either. Consider http://example.com/myroot/MyController/MyAction vs http://example.com/myroot/MyController/MyAction/PageNumber/SomeOtherValue. Now the relative URL will be incorrect.
In the ASPX code, this is easy. I just write in <%= Url.Action("MyAction") %>. But how do I do this in my javascript file?
This is part of the long-standing issue that including server-sided code in JavaScript files is not really possible :(. (Without serious hacks, that is.)
The best solution is to include the action URL inside your HTML file somewhere, then get that value from JavaScript. My suggestion would be something like this:
<!-- in your view file -->
<form id="MyForm" action="<%: Url.Action("MyAction") %>"> ... </form>
<!-- or -->
<a id="MyLink" href="<%: Url.Action("MyAction") %>"> ... </a>
combined with
// In your .js file
$("#MyForm").submit(function ()
{
$.post($(this).attr("action"), data, function (result) { /* ... */ });
return false;
});
// or
$("#MyLink").click(function ()
{
$.getJSON($(this).attr("href"), data, function (result) { /* ... */ });
return false;
});
This feels semantically clear to me, and in some cases even creates degradable fallback behavior for when JavaScript is turned off.
You can't do this in your JavaScript file directly, however you can pass these dynamic values into your script by way of a script initializer. Consider the following example:
External Js file
ShoppingCart = function() {
this.settings = {
AddProductToCartUrl: '',
RemoveFromCartUrl: '',
EmptyCartUrl: '',
UpdateCartUrl: ''
};
};
ShoppingCart.prototype.init = function(settings) {
this.settings = jQuery.extend(this.settings, settings || {});
};
HTML/View
<script type="text/javascript">
var cart = new ShoppingCart();
cart.init({ AddProductToCartUrl: '<%=Url.Action("MyAction")%>' });
alert(cart.settings.AddProductToCartUrl);
</script>
Simple: tell your javascript what the correct URL is.
Tactically, you can get there alot of ways, but they basically break down into two techniques:
Have a server-side generated javascript "configuration" so you can do something like var url = siteConfiguration.SITEROOT + 'products/pink-bunny-slippers' Note this file can be a normal MVC view, the only trick is you have to tell the controller to send a text/javascript header rather than text/html.
Basically, dependency inject it into your script. IE function wireUpAjaxLinksToService(linkIdentifier, serviceEndpoint) where you call using something like wireUpAjaxLinks('a.ajax', '<%= Url.Action("MyService", "Services") %>')

Resources