I have two drop down select tags(g:select), and I want to create ajax logic. when I choose some value from first select, the second select must be update, but something is wrong and nothin is coming to the second one. this is my code:
controller:
def getModels(params) {
def models = Models.findAll {
car.name == params.name
}
println (models.modelName)
return [models:models]
}
view:
<div>
<label class="label_title">Select Maker:</label>
<g:select class="select_styled" name="car_maker" from="${cars.name}"
keys="${cars.name}"
onchange="${remoteFunction(
controller:'home',
action:'getModels',
update: [success:'car_models'],
params: '\'name=\' + this.value')}" />
</div>
<div class="row field_select" >
<label class="label_title">Select Model:</label>
<g:select class="select_styled" name="car_model" id="car_models"
from="${models}" />
</div>
what is the problem?
EDIT:
println (models.modelName) print the right values in console, so, the method call is working, but the problem in returning the models to the view. it returns null
thanks!
Related
I am using Remote Attribute validation
The method is invoked successfully on textchange event. However, the parameters in the action method of the controller does not get the value of the field.
Here is the Action Method in the HomeController.cs. When invoked the Name parameter remains null. I will be pleased if someone solve this problem
[AcceptVerbs("Get", "Post")]
public async Task<ActionResult> IsExist(string Name)
{
List<Keywords> keywords = new List<Keywords>();
HttpClient client = _api.Initial();
HttpResponseMessage res = await client.GetAsync("api/Keywords");
if (res.IsSuccessStatusCode)
{
var result = res.Content.ReadAsStringAsync().Result;
keywords = JsonConvert.DeserializeObject<List<Keywords>>(result);
}
if (keywords.FirstOrDefault(x => x.Name == Name) == null)
{
return Json(false);
}
else
{
return Json(true);
}}
Here is the Model
public partial class Keywords
{
public int Id { get; set; }
[Display(Name = "Name of Keyword")]
[Required]
[Remote(action: "IsExist",controller: "Home", ErrorMessage = "Keyword already present!")]
public string Name { get; set; }}
Here is the razor page in which I want to implement validation
#page
#model Consumer.Pages.Keyword.CreateModel
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Keywords</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Keywords.Name" class="control-label"></label>
<input asp-for="Keywords.Name" class="form-control" />
<span asp-validation-for="Keywords.Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Keywords.Department" class="control-label"></label>
<select asp-for="Keywords.DepartmentId" class="form-control" asp-items="ViewBag.Department"></select>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="Index">Back to List</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
I found the solution. It is to
Remove partial in the model class definition.
Replace in the Razor Page
<input asp-for="Keywords.Name" class="form-control" />
with
<input asp-for="Keywords.Name" name="Name" class="form-control" />
The [Remote] attribute is all but useless. There's a long-standing problem from the ASP.NET MVC days that migrated its way into ASP.NET Core unabated, as well. Namely, the action that handles the remote must take a param that matches the input name of what what's being validated. In other words, your action takes a param, name, but what's being sent to it is Keywords.Name, which cannot bind to name. You'd have to do something like:
public async Task<ActionResult> IsExist(Keywords keywords)
And then, then the value will be available via keywords.Name. This obviously makes the usage highly dependent on the particular implementation, so if there's a situation with a different input name like Foo.Keywords.Name, then you'd need an entirely different action, to match that binding, and basically duplicate the logic (though you could factor out the majority the logic into some common method all the actions could utilize).
Long and short, you're probably better off just handling this yourself manually. Just bind to the input event on the name input, and then call your method via AJAX. Then you can explicitly control the key that's sent in the request body, such that it will always match your action. Just note that you'll also want to debounce sending that AJAX request so that it only happens every few keystrokes or so. Otherwise, you're going to hammer your action.
I'm learning laravel 5.4 and i'm doing a sample project. In that I need to do a search from my DB. Below i have attached a screenshot of my interface.
As you can see in the searchbox i have given i need to search "malabe". And i need to get results for that. i have implemented Controller and needed views too. below i have attached my controller
class SearchController extends Controller
{
//search controller
public function search($keydown){
$searchDetails = DB::table('van_Services')
->where('vs_RouteTo','like','%'.$keydown.'%')
->orwhere('vs_RouteFrom','like','%'.$keydown.'%')
->orwhere('vs_Description','like','%'.$keydown.'%')
->orderBy('created_at', 'DESC')
->paginate(12);
return view('search.search', compact('searchDetails'));
}
}
route code
Route::get('/search/{key}','SearchController#search');
here is the div of my search box code,
<div class="col-xs-6 col-sm-2 col-md-2">
<div class="search_box pull-right">
{{--Search Button--}}
<input type="text" name="search" id="search" laceholder="Search"/>
</div>
</div>
My route and code works if i do the url manual,
my problem is how can i make my search box work? any tutorials or tips?
1. If you really need to use URL link.
JS solution is:
// q => Your search word
function redirectSearch(q) {
location.href = '/search/'+q;
}
pass search field value to this function and page redirect automatically.
.
2. You can send GET params to controller.
Front code:
<div class="col-xs-6 col-sm-2 col-md-2">
<div class="search_box pull-right">
<form action="/search" method="GET">
{{--Search Button--}}
<input type="text" name="search" id="search" placeholder="Search"/>
</form>
</div>
Controller code:
public function search(Request $request){
$search = $request->search;
... Your code ...
}
If you use method with request don`t forget about
use Illuminate\Http\Request;
Route:
Route::get('/search','SearchController#search');
My route and code works if i do the url manual,
I assume it's already working and redirection is just your problem.
Just simply use JS/jQuery.
// when ENTER is pressed
$(document).keypress(function (e) {
if (e.which == 13) {
e.preventDefault();
window.location = APP_URL + "/search/" + $('#search').val();
}
});
Goodluck.
I want to show some flash message after completion of AJAX call. I am doing like this ..
Controller Action --
def subscribe()
{
def subscribe = new Subscriber()
subscribe.email = params.subscribe
if (subscribe.save())
{
flash.message = "Thanks for your subscribtion"
}
}
View Part --
Subscribe :
<g:formRemote onSuccess="document.getElementById('subscribeField').value='';" url="[controller: 'TekEvent', action: 'subscribe']" update="confirm" name="updateForm">
<g:textField name="subscribe" placeholder="Enter your Email" id="subscribeField" />
<g:submitButton name="Submit" />
</g:formRemote >
<div id="confirm">
<g:if test="${flash.message}">
<div class="message" style="display: block">${flash.message}</div>
</g:if>
</div>
My AJAX working fine but it is not showing me flash.message. After refresh page it displaying message. How to solve it ?
When you use ajax your page content isn't re-parsed, so your code:
<g:if test="${flash.message}">
<div class="message" style="display: block">${flash.message}</div>
</g:if>
will not run again.
So I agree with #James comment, flash is not the better option to you.
If you need to update your view, go with JSON. Grails already have a converter that can be used to this:
if (subscribe.save()) {
render ([message: "Thanks for your subscribtion"] as JSON)
}
And your view:
<g:formRemote onSuccess="update(data)" url="[controller: 'TekEvent', action: 'subscribe']" name="updateForm">
<g:textField name="subscribe" placeholder="Enter your Email" id="subscribeField" />
<g:submitButton name="Submit" />
</g:formRemote >
<script type='text/javascript'>
function update(data) {
$('#subscribeField').val('');
$('#confirm').html(data.message);
}
</script>
You have couple options,
First you can try to return the message from your controller in a form of json or a map and render it on the screen your self using javascript libraries, which is a bit different if you want to use Grails ajax tags.
The other option is using a plugin like one-time-data , which
Summary A safe replacement for "flash" scope where you stash data in
the session which can only be read once, but at any point in the
future of the session provided you have the "id" required.
Description
This plugin provides a multi-window safe alternative to flash scope
that makes it possible to defer accessing the data until any future
request (so long as the session is preserved).
more
Hope it helps
I do have this code on my demo.gsp file. But I´m new to grails and I don´t really know very well how to retrieve the value of the input on my Controller to validate it like i.e "inputResult=="hi" then ok else bad".
<g:form action='${postUrl}' method='post' id='loginForm' class='cssform' autocomplete='off'>
<p>
<label for="password">
<g:message code="access.code"/>:
</label>
</p>
<p>
<input name="j_password" class="loghominput" id="password" type="password"/>
</p>
<div class="greenbutton2">
<a href="#" onclick="document.getElementById('loginForm').submit(); return false">
<g:message code="home.enter"/></a><input type="submit" style="display:none" value="Enter"/>
</div>
</g:form>
My Controller is like this.
class AskDemoController {
def demo = {
}
}
Thanks!
You can access parameters submitted by your form in the controller by using the params object. Something like this...
def somethingInTheForm = params.nameOfTheParam;
if (somethingInTheForm){
render 'good'
}else{
render 'bad'
}
Take a look here for documentation.
However - i would suggest going through some to the Tutorials to gain a better understanding of the power of grails.
I have a razor view that I added a delete button to inside of an 'if' statement and when the view is rendered in the browser it is displaying "System.Web.Mvc.Html.MvcForm" next to the delete button.
How do I get rid of it?
Here is the code:
<div id="deletestatusupdate">
#if (update.User.UserName.Equals(User.Identity.Name, StringComparison.OrdinalIgnoreCase))
{
#Html.BeginForm("deleteupdate", "home")
#Html.Hidden("returnUrl", Request.Url.ToString())
<button name="id" value="#update.StatusUpdateId">Delete</button>
}
</div>
Here is how it shows up in the rendered Razor View:
System.Web.Mvc.Html.MvcForm [Delete Button]
pretend that [delete button] is a an actual button, didn't feel like taking a screen shot.
Thank you for your help.
The recommended way to generate a form is the following:
<div id="deletestatusupdate">
#if (update.User.UserName.Equals(User.Identity.Name, StringComparison.OrdinalIgnoreCase))
{
using(Html.BeginForm("deleteupdate", "home"))
{
#Html.Hidden("returnUrl", Request.Url.ToString())
<button name="id" value="#update.StatusUpdateId">Delete</button>
}
}
</div>
Alternatively you could do this:
<div id="deletestatusupdate">
#if (update.User.UserName.Equals(User.Identity.Name, StringComparison.OrdinalIgnoreCase))
{
Html.BeginForm("deleteupdate", "home");
#Html.Hidden("returnUrl", Request.Url.ToString())
<button name="id" value="#update.StatusUpdateId">Delete</button>
Html.EndForm();
}
</div>
The reason why your original approach did not work is because BeginForm() writes directly to the output.
Please use #using instead of using the issue will resolved I am using MVC 4
#using(Html.BeginForm("deleteupdate", "home"))
{
#Html.Hidden("returnUrl", Request.Url.ToString())
<button name="id" value="#update.StatusUpdateId">Delete</button>
}
Get right for this we can use them
Using(Html.Beginform("Delete", "Home", new { Id = item.id } ))
{
#* We right the code. *#
}