I am needing to insert a set of information in the database sqlserver data, but along with them some pictures along with some string. I am wanting to move everything by Json.
below is the input to select the image
<th>
<div class="form-group">
<label for="legendaFoto5">Legenda</label>
<input type="text" class="form-control" id="legendaFoto5" placeholder="Legenda da Foto">
</div>
</th>
and below this the part where I pass along to Json, not this going well until I changed the first "sfoto1InputFile" to be able to upload, but it did not work.
<script type="text/javascript">
$(document).ready(function () {
$("#salvarLevantamentoFicha").click(function (evt) {
var sfoto1InputFile = $("#foto1InputFile").get(0).files[0];
var sfoto2InputFile = $("#foto2InputFile").image;
var sfoto3InputFile = $("#foto3InputFile").image;
var sfoto4InputFile = $("#foto4InputFile").image;
var sfoto5InputFile = $("#foto5InputFile").image;
var strlegendaFoto1 = $("#legendaFoto1").val();
var strlegendaFoto2 = $("#legendaFoto2").val();
var strlegendaFoto3 = $("#legendaFoto3").val();
var strlegendaFoto4 = $("#legendaFoto4").val();
var strlegendaFoto5 = $("#legendaFoto5").val();
$.getJSON("#Url.Content("~/CadLevantamentoAmbiental/SalvarFichaLevantamentoTC")", {
_sfoto1InputFile: sfoto1InputFile,
_sfoto2InputFile: sfoto2InputFile,
_sfoto3InputFile: sfoto3InputFile,
_sfoto4InputFile: sfoto4InputFile,
_sfoto5InputFile: sfoto5InputFile,
_strlegendaFoto1: strlegendaFoto1,
_strlegendaFoto2: strlegendaFoto2,
_strlegendaFoto3: strlegendaFoto3,
_strlegendaFoto4: strlegendaFoto4,
_strlegendaFoto5: strlegendaFoto5
});
});
});
</script>
There are several things that ypu must take into account, and several differences between browsers. So the best that you can do is to use and existing jQuery plugin to get this done, for example:
jQuery File Upload Demo
malsup jQuery Form plugin
The second one is a more general solution, to post a whole form including the file uploads that it contains.
If you try to do it by yourself, without using a plugin, you'll get into big trouble.
Related
I am currently working on a view (in a C# .Net Core 2.1 web application) that is intended to have a "Search string" text box and an "Add Item" button that should open up a modal that will have a list of all items (from the database) that match the search string, with a "Select" button or link in order to add the item.
But I'm at a loss to figure out how to pass the text box results to the modal action.
Note: I know I have a work-around in that I could code it as a completely separate view/action (i.e. not a modal), probably adding logic to the existing form submit action, but it'd be nice if I could keep the modal idea.
Here is the code of what I tried so far (but to no avail):
Controller:
public IActionResult AddItem(string SearchString)
{
var model = _context.BasicItems
.Where(i => i.Name.Contains(SearchString));
return PartialView("_AddKitItem", model);
}
The in the view that I have the text box and button (which now I'm using a ViewModel rather than my original Model entity - note: the ViewModel is just an object containing the original entity I wanted to use - in this case called a Kit - and a string called SearchString):
<div id="modal-placeholder"></div>
(then some other controls)
<label asp-for="SearchString" class="control-label"></label>
<input asp-for="SearchString" class="form-control" />
<button type="button" class="btn btn-primary" data-toggle="ajax-modal" data-target="#add-item" data-url="#Url.Action("AddItem")">
Search Item To Add
</button>
I also have the following JS code (that I took from sample code)
$(function () {
var placeholderElement = $('#modal-placeholder');
$('button[data-toggle="ajax-modal"]').click(function (event) {
var url = $(this).data('url');
$.get(url).done(function (data) {
placeholderElement.html(data);
placeholderElement.find('.modal').modal('show');
});
});
placeholderElement.on('click', '[data-save="modal"]', function (event) {
event.preventDefault();
var form = $(this).parents('.modal').find('form');
var actionUrl = form.attr('action');
var dataToSend = form.serialize();
$.post(actionUrl, dataToSend).done(function (data) {
var newBody = $('.modal-body', data);
placeholderElement.find('.modal-body').replaceWith(newBody);
var isValid = newBody.find('[name="IsValid"]').val() == 'True';
if (isValid) {
placeholderElement.find('.modal').modal('hide');
}
});
});
});
When that didn't work (by putting a breakpoint on the first line of the AddItem action in the controller and checking the SearchString value - which was null), on the main view I replaced the two SearchString controls with the following
#Html.DisplayNameFor(model => model.SearchString)
:
#Html.DisplayFor(model => model.SearchString)
But still no luck - same result.
So then I even tried:
Item Name:
#Html.TextBox("SearchString")
And still the same outcome.
Scott use
asp-for="#model.SearchString"
I have been trying to research this for a while and I have found one person with a similar problem but there was no solution to his question:
https://github.com/twitter/typeahead.js/issues/1340
Some of my bloodhound objects are producing expected results into local storage however two of them are missing the data (datums). Even though they are missing the datum part everything else works. I can search with type-ahead as expected. I would like to know why these two objects don't have the data stored.
I now try to use cacheKey attribute instead of the default so this image does not show me using the cacheKey attribute.
Sample Image : Local Storage
Here is a part of my code that uses typeahead. The typeahead works but it's not being stored in local storage:
JavaScript:
var sections = new Bloodhound({
datumTokenizer: function (d) {
$(".loadingSections").hide();
var namepartTokens = Bloodhound.tokenizers.nonword(d);
var nameTokens = Bloodhound.tokenizers.whitespace(d);
var allTokens = namepartTokens.concat(nameTokens);
return allTokens;
},
queryTokenizer: Bloodhound.tokenizers.whitespace,
prefetch: {
url: classLookUp,
cacheKey: 'sectionLookUp'
}
});
sections.initialize();
$(".section-lookup .typeahead").typeahead({ highlight: true }, {
source: sections.ttAdapter()
});
HTML
...
<script>
var classLookUp = '#Url.Action("GetClassNames", "Home")';
...
</script>
...
<div class="form-group section-lookup">
<div class="loadingSections"></div>
<label class="control-label col-sm-2">Section:</label>
<div class="col-sm-10">
#Html.TextBoxFor(x => x.DisplayName, new { #class = "form-control typeahead", #id = "editLookup", #placeholder = "ex. 15/FA CIS-131-102" })
</div>
</div>
<button type="button" id="editSearch" class="btn btn-primary col-sm-offset-4 col-sm-4">Search for Course</button>
C#
[HttpGet]
public ActionResult GetClassNames()
{
try
{
var newSections = this.repo.Courses;
var names = newSections.Select(course => course.DisplayName).ToList();
return this.Json(names, JsonRequestBehavior.AllowGet);
}
catch (DatabaseConnectionException)
{
return this.Json(new { failure = true }, JsonRequestBehavior.AllowGet);
}
}
Note: I seem to be far away from exceeding localstorage max storage
I finally found out why it's not being stored in local storage. The reason is exceeding local storage max storage. I found out at the end of the datum section being stored there is a trie attribute that it stores along with it. Even if your list has only 3,000 elements the trie attached with it is massive enough to take a lot of storage space. So there was unknown overhead.
trie: It seems to be the tree for searching. I would like a way to store only the datum section and have the tree always generated client side. This way we can have more things stored on local storage. Not having this as a default defeats the purpose of prefech which the idea was to not having calls to the server. I know the tree is being build client side but we do not need to have it saved in local storage.
I'm working on an MVC project in which jsrender is used.
This is my first time working with jsrender (in fact I'm fairly new at javascript and C# too lol) and I've been struggling with one particular problem for a full day now.
I have the following javascript
$.post('#Url.Action("GetDocs","Place", new { placeID = Model.PlaceId})').done(
function (data) {
var template = $.templates("#doc-tmpl");
var htmlOut = template.render(data.documents);
$("#documentListContainer").append(htmlOut);
$(".docCount").html(data.count);
});
This gets all the data I need for the template below, but I need to create an Url.Action() using a piece of that data.
<script id="doc-tmpl" type="text/x-jsrender">
<div class="col-md-4">
<h5>{{:Name}}{{:test}}</h5>
<p id="DocId" class="hidden"><br />{{:DocId}}</p>
<img src="data:image;base64,{{:FrontCoverImg}}" width="140" height="230" />
Link
</div>
I need to supply the docId from the data in the routeValues of the #Url.Action("DisplayPDF","Place", new { docId = "{{:docId}}" }).
Obviously this isn't working in it's current state.
I've looked at the jsrender documentation and other Q&A to do with jsrender and MVC but I'm having trouble wrapping my head around the way it works.
one thing I have thought of is to create the #Url.Action() within the javascript and use a tag to pop it in the template, however I haven't been able to figure out how to add to the data from the $.post in order to make a tag available for it.
Edit:
What I mean from the above paragraph is, the data returned by the javascript/getDocs post is something like:
documents": [
{
"DocId": "86f86a32-5005-456c-8dd1-c023a66dd794",
"Name": "How to...",
"FrontCoverImg": "Base64String(docImg)"
},
{
"DocId": "d29f8afc-3191-47f1-9b88-1de08582ba27",
"Name": "A Document",
"FrontCoverImg": "Base64String(docImg)"
}
],
"count": 2
}
Which is then set up to fill in the template. I'm hoping there is a way to add the #Url.Action() statement to those key/value pairs, something like:
"viewdoc" : '##Url.Action("DisplayPDF", "Place", new {DocId = ' + DocId + ', ##class = "btn btn-default" })';
(not sure if the syntax is quite right there) so I could then put {{:viewdoc}} into the template.
Am I at least on the right track? lol
try this ,
var id = $('#docId').val();
var link = '#URL.Action("download file", "download", new { id = "-1" })';
link = link.replace("-1", id);
Source : How to access javascript variable within #URL.Action()
Ok so after leaving it alone for a week then much experimentation and googling, I found my solution.
I've created the link in the controller, where the JSON data is set.
I had to request the leftmost part of the URL and hardcode the controller/action part of the url, otherwise it crammed the new url on the end of the current page url.
So the solution is as follows:
The Controller:
foreach (Doc document in docs)
{
DocJson dj = new DocJson();
dj.DocId = document.DocId;
dj.Name = document.Comments;
//get base Url
var request = HttpContext.Request.Url.GetLeftPart(UriPartial.Authority);
dj.docLink = request + "/Place/DisplayPDF?DocId=" + document.DocId;
//get image bytes
var docImg = document.FrontCoverImg;
dj.FrontCoverImg = Convert.ToBase64String(docImg);
documents.Add(dj);
}
return Json(new { documents = documents, count = documents.Count() }, JsonRequestBehavior.AllowGet);
(in the view)
The Javascript getting the data:
//getDocs
$.post('#Url.Action("GetDocs","Place", new { placeID = Model.PlaceId})').done(
function (data) {
console.log(data);
var template = $.templates("#doc-tmpl");
var htmlOut = template.render(data.documents);
$("#documentListContainer").append(htmlOut);
$(".docCount").html(data.count);
});
(in the view)
And the template itself:
#* Document jsrender template *#
<script id="doc-tmpl" type="text/x-jsrender">
<div class="col-md-4">
<a href="{{:docLink}}" target="_blank">
<h5>{{:Name}}</h5>
<p id="DocId" class="hidden"><br />{{:DocId}}</p>
<img src="data:image;base64,{{:FrontCoverImg}}" width="140" height="230" />
</a>
</div>
</script>
I have a screen that uses jQuery tabs and was wondering if somehow I can keep the selected tab after a refresh of the page (JS .reload();)?
Any guidance appreciated.
https://github.com/carhartl/jquery-cookie
or
http://code.google.com/p/cookies/downloads/detail?name=jquery.cookies.2.2.0.js.zip&can=2&q=
Example for jquery.cookies.2.2.0.js
$(document).ready(function () {
var initialTabIndex = 0;
var jCookies = jQuery.cookies;
//alert('getting ' + jCookies.get("currentTab"));
if(jCookies.get("currentTab") != null){
initialTabIndex = jCookies.get("currentTab");
}
$('#tabs').tabs({
activate : function(e, ui) {
//alert('setting ' + ui.newTab.index());
jCookies.set("currentTab", ui.newTab.index().toString());
},
active : initialTabIndex
});
});
While the previous answer using cookies will certainly work, it is probably not the ideal solution given peoples aversions to accepting cookies. (it also means you would need to show a disclaimer on your site stating you use cookies, at least to EU visitors). I'd recommend avoiding using cookies where possible so your site remains functional if cookies are disabled/rejected.
A better way is to use the "hash" on the end of a URL.
Modify your tab links as follows:
<div id="UITabs">
<ul>
<li>Tab 1</li>
<li>Tab 2</li>
<li>Tab 3</li>
</ul>
<div id="Tab1"></div>
<div id="Tab2"></div>
<div id="Tab3"></div>
</div>
Then in your head, add the following javascript to ensure the hash is set when changing tabs, and get the hash on pageload and display the required tab:
$(document).ready(function () {
$(function () {
$("#UITabs").tabs();
$("#UITabs").bind("tabsshow", function (event, ui) {
location.hash = ui.newTab.find('a.ui-tabs-anchor').attr('href');
});
$(window).bind('hashchange', function (e) {
$("#UITabs").tabs("select", location.hash);
});
});
});
I'm working on an intranet web app using ASP.NET MVC4 and Entity Framework. On one of my views, I have a list of persons which might be huge in the future. So, to make things easier, I wanted to implement an autocomplete field component using jQuery UI and Json.
The thing is that when I'm using my database to provide a source to my jQuery code, it is not working. However, when I create a variable by hard coding data, it works.
My Action :
public ActionResult AutoComplete(string term)
{
BuSIMaterial.Models.BuSIMaterialEntities db = new Models.BuSIMaterialEntities();
//var result = new [] {"A","B","C","D","E","F"}; with this, it works
var result = (from obj in db.Persons where obj.FirstName.ToLower().Contains(term.ToLower()) select obj).ToArray(); // with this, it doesn't work
return Json(result, JsonRequestBehavior.AllowGet);
}
My View :
#{
ViewBag.Title = "Auto";
}
<h2>Auto</h2>
<label for="persons">Persons : </label><input type="text" id="persons" name="persons"/>
#section Scripts
{
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/bundles/jqueryui")
#Styles.Render("~/Content/themes/base/css")
<script type="text/javascript" language="javascript">
$(document).ready(function () {
$('#persons').autocomplete({
source: '#Url.Action("AutoComplete")'
});
});
</script>
}
I tried to modify my return type (JsonResult instead of ActionResult) but nothing changes. Any idea to solve this problem?
The reason your code doesn't work is because you are attempting to send a domain model to the view which most probably contains circular references in its object graph and is not JSON serializable. To fix the problem do this:
public ActionResult AutoComplete(string term)
{
BuSIMaterial.Models.BuSIMaterialEntities db = new Models.BuSIMaterialEntities();
//var result = new [] {"A","B","C","D","E","F"}; with this, it works
var result = db
.Persons
.Where(p => p.FirstName.ToLower().Contains(term.ToLower()))
.Select(p => p.FirstName) // <!-- That's the important bit you were missing
.ToList();
return Json(result, JsonRequestBehavior.AllowGet);
}
Notice how I am projecting the Person entity to a string (taking only its FirstName). In your example you were directly taking the entire Person object which doesn't make sense for the autocomplete plugin as you need to send an array of strings to the view.