At the moment, I have the following code:
main.js:
$(function () {
var keys = ["test1", "test2", "test3", "test4"];
$("#keywords-manual").autocomplete({
minLength: 2,
source: keys
});
});
Test.cshtml:
#model App.Models.Service
#{
ViewBag.Title = "Test";
}
<script src="~/Scripts/main.js"></script>
<h2>#ViewBag.Title.</h2>
<h3>#ViewBag.Message</h3>
#using (Html.BeginForm("SaveAndShare", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<h4>Create a new request.</h4>
<hr />
#Html.ValidationSummary("", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(m => m.ServiceType, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.ServiceType, new { #class = "form-control", #id = "keywords-manual" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Submit!" />
</div>
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
The point is that currently I have just provided 4 constant values to the autocomplete. But then I created a database and a table named "services", which comes from my model named Service. I have already provided a few rows to the table with values. I have a field in my table called ServiceType, and I want the autocomplete to take the values of that column as a source. Please note that I have hosted my database in Azure and it is MySQL, though, I think it doesn't matter here. Can you tell me how can I take as a source the values of ServiceType column that is located inside my services table?
As far as I can tell by your question, it should look something like this:
$("#keywords-manual").autocomplete({
source: function (request, response) {
$.ajax({
url: "/Home/GetServiceTypes",
data: "{ 'keywords': '" + request.term + "' }",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
dataFilter: function (data) { return data; },
success: function (data) {
response($.map(data, function (item) {
return {
label: item.value,
value: item.value,
id: item.id
}
}))
}
});
},
minLength: 2
});
And the controller,
YourContext db = new YourContext();
public JsonResult GetServiceTypes() {
db.ServiceType.Where(s => keywords == null || s.Name.ToLower()
.Contains(keywords.ToLower()))
.Select(x => new { id = x.ServiceTypeID, value = x.ServiceTypeName }).Take(5).ToList();
return result;
}
Apologies for any typos, but that should be the jist of it. If you need to be searching for more than one keyword, in the controller method, split the value from 'keywords-manual' into a string array, then use a foreach loop or similar approach to match each value, adding matches to a total list each time.
** I say string array, that's pretty oldschool, split it into a list :)
Related
Okay I'm totally new to this so I'm not going to get a lot of the terminology right, but it's an ASP.NET MVC application where a create view is supposed to have an autocomplete function on the "StudentID" text box. It doesn't work. On the console window I get an error message "Autocomplete is not a function". This is strange because the intellisense at the beginning does give me autocomplete. I don't know what I'm supposed to paste below but I put in the javascript as well as the applicable Controller code. LMK if there's anything else you need to see. Thanks in advance.
P.S. If you know a better way to do autocomplete (this is done through a class that we got the code from some website and looks more complicated than similar things I did in the past) please let me know that too.
<script>
$("#Student_FirstName").autocomplete(
{
source: function (request, response)
{
$.ajax(
{
url: "/Enrollments/GetStudents",
dataType: "json",
type: "POST",
data:
{
term: request.searchTerm
},
success: function (data) {
console.log(data);
response($.map(data, function (item) {
return {
label: item.Name, value: item.Name, id: item.id
};
}))
}
});
},
minLength: 2,
select: function (event, query)
{
console.log(query);
$("#StudentID").val(query.item.id);
}
});
</script>
And now from later on in the Create view:
<div class="form-group">
#Html.LabelFor(model => model.StudentID, "StudentID", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Student.FirstName, new { htmlAttributes = new {#class = "form-control"}})
#Html.HiddenFor(model => model.StudentID)
#Html.ValidationMessageFor(model => model.StudentID, "", new { #class = "text-danger" })
</div>
</div>
And finally from the Controller Class:
// GET: Enrollments/Create
public ActionResult Create()
{
ViewBag.CourseID = new SelectList(db.Courses, "CourseID", "Title");
ViewBag.StudentID = new SelectList(db.Students, "StudentID", "LastName");
ViewBag.InstructorID = new SelectList(db.Instructors, "ID", "FirstName");
return View();
}
// POST: Enrollments/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "EnrollmentID,Grade,CourseID,StudentID,InstructorID")] Enrollment enrollment)
{
if (ModelState.IsValid)
{
db.Enrollments.Add(enrollment);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CourseID = new SelectList(db.Courses, "CourseID", "Title", enrollment.CourseID);
ViewBag.StudentID = new SelectList(db.Students, "StudentID", "LastName", enrollment.StudentID);
ViewBag.InstructorID = new SelectList(db.Instructors, "ID", "FirstName", enrollment.InstructorID);
return View(enrollment);
}
Right now, on my page I have a button at the top of one of my views <button type="button" id="show">Find Project</button> that when pressed, renders a partial view (which is a table) at the bottom of the page. My layout is formatted as:
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<!--this is my navbar-->
</div>
<div class="container body-content">
#RenderBody()
</div>
<div class="wrapper">
<!-- TABLE WILL APPEAR HERE -->
</div>
</body>
The javascript that makes the table appear is:
$(document).ready(function() {
$("#show").on("click", function() {
$.ajax({
url: '/Projects/SearchTable',
type: "GET"
}).done(function(partialViewResult) {
$(".wrapper").html(partialViewResult);
$(".wrapper").css('display', 'block');
});
});
});
/Projects/SearchTable is the controller action that renders the partial view:
[HttpGet]
public ActionResult SearchTable()
{
var states = GetAllStates();
var model = new ProjectClearanceApp.Models.ProjectViewModel();
model.States = GetSelectListItems(states);
model.Projects = from m in db.Projects select m;
return PartialView("~/Views/Projects/_ClearedProjects.cshtml", model);
}
The text boxes are dispersed throughout my main view, and all appear in the same format:
<div class="col-md-5 entry-field">
#Html.LabelFor(model => model.Project.FirstNamedInsured, htmlAttributes: new { #class = "control-label" })
#Html.TextBoxFor(model => model.Project.FirstNamedInsured, new { #class = "form-control text-box single-line", maxlength=150 })
#Html.ValidationMessageFor(model => model.Project.FirstNamedInsured, "", new { #class = "text-danger" })
</div>
Except for two dropdowns that are formatted like so:
<div class="col-md-3 address-info">
#Html.LabelFor(m => m.Project.FirstNamedInsuredAddress.State, htmlAttributes: new { #class = "address-label" })
#Html.DropDownListFor(m => m.Project.FirstNamedInsuredAddress.State,
Model.States,
"--",
new { #class = "form-control address-entry" })
#Html.ValidationMessageFor(model => model.Project.FirstNamedInsuredAddress.State, "", new { #class = "text-danger" })
</div>
where Model.States is an enumerable to populate the drop down list with all of the states.
Is it possible to get the data from those textboxes and pass them as data/arguments to the controller for use in the partial view without submitting a form or refreshing the page?
Send the parameter like this:
public ActionResult SearchTable(string firstNamedInsured)
{
//Use the parameter in the model or any where
var states = GetAllStates();
var model = new ProjectClearanceApp.Models.ProjectViewModel();
model.States = GetSelectListItems(states);
model.Projects = from m in db.Projects select m;
return PartialView("~/Views/Projects/_ClearedProjects.cshtml", model);
}
And javascript:
$(document).ready(function () {
$("#show").on("click", function () {
$.ajax({
url: '/Projects/SearchTable?firstNamedInsured=' + $('#' + #Html.IdFor(m => m.Project.FirstNamedInsured)).val(),
type: "GET"
}).done(function (partialViewResult) {
$(".wrapper").html(partialViewResult);
$(".wrapper").css('display', 'block');
});
});
});
I have finish autocomplete with a jquery library which is
using jquery-ui-1.12.1.min.js
. I have modified it to make to get the search with username and full name. it will show as below image
when I select the value it will paste the whole text into an input box.
here is my question how do it modify it to show as the image but when I select the value it will only paste the username into input box?
how i only want nonstop00000 paste it into input box when i select the 1st value
here is my javascript
$(document).ready(function () {
$("#id").autocomplete({
source: function(request,response) {
$.ajax({
url: '#Url.Content("~/UserManagement/AutoCompleteUser")/',
type: "POST",
dataType: "json",
data: { term: request.term },
success: function (data) {
response($.map(data, function (item) {
return [{ label: item.Username + " | " + item.FullName, value: item.id }];
}))
}
})
},
messages: {
noResults: "", results: ""
}
});
})
here is my search controller
if (!String.IsNullOrEmpty(searchString))
{
user = user.Where(s => s.Username.Trim().Contains(searchString.Trim())
|| s.FullName.Trim().Contains(searchString.Trim()));
}
here is my autocomplete controller
public JsonResult AutoCompleteUser(string term)
{
var result = (from r in db.UserTables
where ((r.Status == "Active") && (r.Username.ToLower().Contains(term.ToLower()) || (r.FullName.ToLower().Contains(term.ToLower()))))
select new { Username = r.Username, FullName = r.FullName }).Distinct();
return Json(result);
}
here is my view
<div class="col-lg-9 col-md-9 col-sm-9 col-xs-12 search-panel">
#using (Html.BeginForm("Index", "UserManagement", FormMethod.Get))
{
<div class="input-group form-group ui-widget">
#Html.TextBox("id", ViewBag.CurrentFilter as string, new { #class = "form-control autocomplete", #placeholder = "Search for..." })
<span class="input-group-btn">
<input type="submit" value="Search" class="form-control autocomplete " />
</span>
</div>
}
</div>
To achieve this you can use the select event to amend the value to be placed in to the input. Try this:
$("#id").autocomplete({
// your settings...
select: function(e, ui) {
e.preventDefault();
$('#id').val(ui.item.label.split('|')[0].trim());
}
});
I am using select2-jquery to bring several items from the server (ajax) and the allow the user to select several of them, it works fine but I cannot select any given tag more than once and that's a requirement I'll paste some of my code, hopefully it helps. I have inspected the ajax requests and i can see the same data getting back from the server under the same search terms, but once an item is selected the select2 does NOT displays it anymore
This is a part of my View:
<div class="form-group">
#Html.LabelFor(m => m.Vals, T("Values"), new { #class = "control-label col-md-2" })
<div class="col-md-7">
<input id="Values" name="Values" type="hidden" style="width: 100%" data-url="#Url.Action("Action", "Controller")" />
</div>
</div>
And this is the JS part:
$(function () {
var fullTemplateString = 'some template string';
var resultTemplateString = 'other template';
var $selectInput = $('#Values');
initilizeSelect2($selectInput, fullTemplateString, resultTemplateString);
});
function initilizeSelect2($selectInput, fullTemplate, resultTemplate) {
$selectInput.select2({
placeholder: "Select Labs",
minimumInputLength: 2,
multiple: true,
tokenSeparators: [","],
tags: false,
ajax: {
url: $selectInput.data('url'),
dataType: 'json',
quietMillis: 250,
data: function(term, page) {
return {
term: term,
};
},
results: function(data, page) {
return {
results: data
};
}
},
formatSelection: function (item) {
return format(item, resultTemplate);
},
formatResult: function (item) {
return format(item, fullTemplate);
},
escapeMarkup: function (m) { return m; }
});
}
function format(item, templateString) {
var result = templateString
.replace(/\^\^id\^\^/g, item.id)
.replace(/\^\^icon\^\^/g, item.icon)
.replace(/\^\^text\^\^/g, item.name)
.replace(/\^\^desc\^\^/g, item.desc);
return result;
}
I am using select2 version:3.4.5 extensively in this project so any changes in this regard would be very painful
Thanks in advance
after a lot of search and debugging through the select2 code i found a way (hack) to pull this out by removing the css class .select2-selected that prevents already selected elements from displaying again. I know this isn't the best solution there is, but it is working now. I really welcome any improvements or better solutions
I am developing MVC application and using razor syntax.
In this application I am giving comment facility.
I have added a partial view, which loads the comment/Records from DB.
In below image, we can see the comment box which is called run-time for employee index view.
Now as we can see comment box, I called at run-time, which is partial view, but problem is I can add comment for only on first record...after first record that button wont work at all...
anything is missing ?
Is there separate process when we call any partial view run-time and make in action on it ?
See the pic...
Here is the code....
#model PagedList.IPagedList<CRMEntities.Customer>
<link href="../../Content/Paging.css" rel="stylesheet" type="text/css" />
<link href="../../Content/EventEntity.css" rel="stylesheet" type="text/css" />
<script src="<%=Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")%>" type="text/javascript"></script>
<div id="ListBox">
<div id="ListHeader">
All customers(#Model.TotalItemCount)
</div>
#foreach (var item in Model)
{
<div id="ListContent">
<span class="ContentTitleField">#Html.ActionLink(item.Name, "Details", new { id = item.Id }, new { #style="color:#1A6690;" })</span>
#if (item.Owner != null)
{
<span class="ContentSecondaryField">#Html.ActionLink(item.Owner.FullName, "Details", "Employee", new { id = item.OwnerId }, new { #style = "color:#1A6690;" })</span>
}
<span class="ContentSecondaryField">#Html.DisplayFor(modelItem => item.Address)</span>
<span id="flagMenus">
#Html.Action("ShowFlag", "Flagging", new { entityId=item.Id, entityType="Customer"})
</span>
#if (item.Opportunities.Count > 0)
{
<span class="FlagOpportunity">#Html.ActionLink("opportunities(" + item.Opportunities.Count + ")", "Index", "Opportunity", new { custid = item.Id }, new { #style = "color:#fff;" })</span>
}
<div style="float:right;">
#Html.Action("SetRate", "Rating", new { entityId = item.Id, rating = item.Rating, entityname = "Customer" })
</div>
<div id="subscribeStatus" style="float:right;">
#Html.Action("ShowSubscribedStatus", "Subscribing", new { entityId = item.Id, entityType = "Customer" })
</div>
<div class="ListLinks">
<span class="ListEditLinks">
<span style="float:left;">#Html.ActionLink("edit", "Edit", new { id = item.Id })</span>
<span class="LinkSeparator"></span>
</span>
<span class="ListAddLinks">
<span style="float:left;">#Html.ActionLink("+opportunity", "Create", "Opportunity", new { custid = item.Id }, null)</span>
<span class="LinkSeparator"></span>
<span>#Ajax.ActionLink("+Comment", null, null, null, new { id = item.Id, #class = "addremark" })</span>
</span>
<div class="RemarkBox"></div>
</div>
<span class="CommentAdd">
</span>
<div class="CommentBlock">
</div>
<span>#Ajax.ActionLink("Add Comment", null, null, null, new { id = item.Id, #class = "addremark" })</span>
</div>
}
<div class="PagingBox">
#Html.Action("CreateLinks", "Pager", new { hasPreviousPage = Model.HasPreviousPage, hasNextPage = Model.HasNextPage, pageNumber = Model.PageNumber, pageCount = Model.PageCount })
</div>
</div>
<script type="text/javascript">
$(document).ready(function () {
$('.RemarkBox').hide();
$('a.addremark').click(function () {
var url="#Html.Raw(Url.Action("ShowCommentBox", "Comment", new { Id = "idValue", EntityType = "Customer" }))";
url=url.replace("idValue",event.target.id);
$('.RemarkBox').load(url);
$(this).closest('div').find('div.RemarkBox').slideToggle(300);
return false;
});
$("a.pagenumber").click(function () {
var page = 0;
page = parseInt($(this).attr("id"));
$.ajax({
url: '#Url.Action("GetPagedCustomers")',
data: { "page": page },
success: function (data) { $("#customerlist").html(data); }
});
return false;
});
});
</script>
To expand on what Alberto León is saying, the partial page load will not cause the document ready event to fire, so the re-rendered elements will not have the javascript event handlers registered after the first comment is added.
To resolve this, you could put the event registration code into a function, and call this both from the document ready event and the success handler of the AJAX call. Something like this:
function AssignEventHandlers() {
$('a.addremark').click(function () {
....
});
$("a.pagenumber").click(function () {
var page = 0;
page = parseInt($(this).attr("id"));
$.ajax({
url: '#Url.Action("GetPagedCustomers")',
data: { "page": page },
success: function (data) {
$("#customerlist").html(data);
AssignEventHandlers();
}
});
return false;
});
}
$(document).ready(function () {
$('.RemarkBox').hide();
AssignEventHandlers();
}
In success function you need to recall the javascript, or the jquery code that makes the button work. Is an error that taked me a lot of time. Anything uploaded by ajax or any renderpartiAl needs to recall javascript.
$('.RemarkBox').load(url, function() {
//RECALL JAVASCRIPT
});