Autocomplete not working in jQuery - asp.net-mvc-4

I am trying to get all usernames in jQuery autocomplete but it doesn't seem to work at all.
controller-
public ActionResult Allusers(string Email) {
if (ModelState.IsValid) {
var allUser = (from us in db.SystemUsers
select new UserModel
{
Email=us.Email,
UserId=us.UserId
}).Distinct().ToArray();
// ViewBag.Team = allUser.OrderBy(x => x.Text);
return Json(allUser,JsonRequestBehavior.AllowGet);
}
return View();
}
Script-
<script type="text/javascript">
$(function () {
$("input #autocomplete").autocomplete({
source: function (request, response) {
$.ajax({
url: '/AllUsers/AllUsers/',
type: "POST",
dataType: "json"
});
}
});
});
</script>
Following scripts I am using for it-
<script src="../../Scripts/jquery.unobtrusive-ajax.min.js" type="text/javascript"></script>
<script src="../../Scripts/jquery-1.6.2.min.js" type="text/javascript"></script>
<script src="../../Scripts/jquery-ui-1.8.11.js" type="text/javascript"></script>
But no luck.

Try as follows
<script type="text/javascript">
$(function () {
var itemList = [];
$("input #autocomplete").autocomplete({
source: function (request, response) {
$.ajax({
url: '/AllUsers/AllUsers/',
type: "POST",
dataType: "json",
Sucess: function(result) {
$.each(result, function (index, item) {
itemList.push({ label: item.Email, value: item.UserId});
});
}
});
response(itemList);
}
});
});

You need to define success function and fill the response parameter
Refer to the JQuery autocomplete remote json

I was also stucked in this however below worked for me.
In my case my json result was array of string, so there was no column for the returned data.
If you are using .cshtml instead of html then you must have to add/register javascript and css files in bundle config
Render required files in your shared or respective cshtml file.
After that in your cshtml file add below line:
<input type='text' id='stockName'/>
Below part is very tricky and important:
$(function () {
$('#stockName').autocomplete({
source: function (request, response) {
$.getJSON("/EquityList/GetStockNames?term=" + request.term, function (data) {
var realArray = $.makeArray(data)
response($.map(realArray, function (item) {
return {
value: item,
id: item
}
}))
});
},
minLength: 3,
delay: 0
});
});
Important Note:
1) we need to format json data into array first
2) then we need to use map function, this well format the data in to the required format for autocomplete. Until and unless this data formatting is not done, suggestion dialog box UI will not be displayed.
Hope this one helps other developers.

Related

How to mock an image with a fixture in cypress

I'm using cypress to test my VueJS application. The one thing I'm having trouble with is mocking an image to be displayed on the page. For my use case, I'm simply loading a user profile with the following code:
describe('Test Login', () => {
it('Can Login', () => {
cy.server();
cy.route({
method: 'GET',
url: '/api/account/',
response: 'fx:profile.json',
});
cy.route('**/media/demo1.png', 'fx:demo1.png');
});
});
fixtures/profile.json
{
"avatar": "http://localhost:8080/media/demo1.png",
"username": "cypress",
"email": "email#cypress.io",
"pk": 1,
"is_staff": true,
"is_superuser": true,
"is_active": true
}
The profile fixture data is loading correctly in the test. In my fixtures folder, I also have a demo1.png file. I am expecting this image to be loaded and displayed on the page during my test, but it is being displayed as a broken image.
In the network tab, it shows demo1.png as a broken image with a 200 response code and type of text/html.
The cypress documentation mostly discusses images in the context of uploading images, but I haven't been able to find an example of how I can mock an image that is loaded through a <img> tag. Is there an easier way of doing this?
I am not sure if this answer can help you. But at least it is a workaround for this problem ;-)
Say we have a HTML like this:
<html>
<body>
<button id="button">load</button>
<div id="profile">
</div>
<script>
function httpGetAsync(theUrl, callback)
{
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
callback(JSON.parse(xmlHttp.responseText));
}
xmlHttp.open("GET", theUrl, true); // true for asynchronous
xmlHttp.send(null);
}
document.getElementById("button").addEventListener("click", () => {
httpGetAsync("/api/account/", (result) => {
var div = document.querySelector("#profile");
var img = document.createElement("img");
img.src = result.avatar;
div.appendChild(img)
})
})
</script>
</body>
</html>
source: HTTP GET request in JavaScript?
And you want to load the profile after the click was done. Then you can use MutationObserver to replace the img.src.
First, write the MutationObserver:
var observeDOM = (function(){
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
return function( obj, callback ){
if( !obj || !obj.nodeType === 1 ) return; // validation
if( MutationObserver ){
// define a new observer
var obs = new MutationObserver(function(mutations, observer){
callback(mutations);
})
// have the observer observe foo for changes in children
obs.observe( obj, { childList:true, subtree:true });
}
else if( window.addEventListener ){
obj.addEventListener('DOMNodeInserted', callback, false);
obj.addEventListener('DOMNodeRemoved', callback, false);
}
}
})();
(heavily copy & pasted from Detect changes in the DOM)
Now you are able to do this:
describe('Test Login', () => {
it('Can Login', () => {
var win = null;
cy.server();
cy.route({
method: 'GET',
url: '/api/account/',
response: 'fx:profile.json'
});
cy.visit("index.html").then(w => {
cy.get("#profile").then(pro => {
var e = pro[0];
observeDOM(e, (m) => {
// add a red dot image
m[0].addedNodes[0].src = "data:image/png;base64,"+
"iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGdBTUEAALGP"+
"C/xhBQAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9YGARc5KB0XV+IA"+
"AAAddEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q72QlbgAAAF1J"+
"REFUGNO9zL0NglAAxPEfdLTs4BZM4DIO4C7OwQg2JoQ9LE1exdlYvBBeZ7jq"+
"ch9//q1uH4TLzw4d6+ErXMMcXuHWxId3KOETnnXXV6MJpcq2MLaI97CER3N0"+
"vr4MkhoXe0rZigAAAABJRU5ErkJggg=="
})
})
cy.get("button").click()
})
});
});
(yeah at least some lines of code are written on my own ;-P)
You can read the image from the img.src attribute from the fixtures folder. For the sake of simplicity I have used a static base64 string here.
And the result:
We are not using this kind of stuff in our aurelia app but I tried similar things in a private project some time ago.

How To Use FormData() For Uploading File In Vue

So I had asked a question previously, and got a little bit of help as far as logging the results however my results are not making sense.
So I have a input
<input type="file" name="import_file" v-on:change="selectedFile($event)">
The v-on:change binds the selected file to my data object this.file
selectedFile(event) {
this.file = event.target.files[0]
},
and then I submit the file with this method
uploadTodos() {
let formData = new FormData();
formData.append('file', this.file);
for(var pair of formData.entries()) {
console.log(pair[0]+ ', '+ pair[1]);
}
this.$store.dispatch('uploadTodos', formData);
}
However when I submit it seems there is no data attached to formData because my logged result is this
file, [object File]
shouldn't I have my actual data appended to the formData object??
I have referenced other articles on how to post but I am not getting the desired results.
article 1
article2
uploadTodos(context, file) {
console.log(file)
axios.post('/import', file,{ headers: {
'Content-Type': 'multipart/form-data'
}})
.then(response => {
console.log(response.data)
context.commit('importTodos', response.data)
})
.catch(error => {
console.log(error.response.data)
})
}
when I console.log(file) the formData object is empty
Backend Question
So my issue with Laravel on the backend is with the maatwebsite package. From what I have seen is the 3.0 version does not yet support imports. And the only work around suggested is to install version 2.0? Is this still the only workaround? Here is the controller method
public function importExcel(Request $request)
{
if (empty($request->file('file')->getRealPath())) {
return back()->with('success','No file selected');
}
else {
$path = $request->file('file')->getRealPath();
$inserts = [];
Excel::load($path,function($reader) use (&$inserts)
{
foreach ($reader->toArray() as $rows){
foreach($rows as $row){
$inserts[] = ['user_id' => $row['user_id'], 'todo' => $row['todo']];
};
}
});
if (!empty($inserts)) {
DB::table('todos')->insert($inserts);
return back()->with('success','Inserted Record successfully');
}
return back();
}
}
The line not suppported by version 3.0 is this
Excel::load($path,function($reader) use (&$inserts)
I have reproduced your code and it seems to be working fine
when I console.log(file) the formData object is empty
Yeah the output should be an empty object when you console, that's the way javascript works.
after casting the output to an array i get the output in the image below:
const store = new Vuex.Store({
actions: {
uploadTodos(context, file) {
console.log([...file])
axios.post('/import', file,{ headers: {
'Content-Type': 'multipart/form-data'
}})
.then(response => {
console.log(response.data)
context.commit('importTodos', response.data)
})
.catch(error => {
console.log(error.response.data)
})
}
}
})
const app = new Vue({
store,
data: {
file: null
},
methods: {
selectedFile(event) {
console.log(event);
this.file = event.target.files[0]
},
uploadTodos() {
let formData = new FormData();
formData.append('file', this.file);
for(var pair of formData.entries()) {
console.log(pair[0]+ ', '+ pair[1]);
}
this.$store.dispatch('uploadTodos', formData);
}
},
el: '#app'
})
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vuex"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<div id="app">
<input type="file" name="import_file" #change="selectedFile($event)">
<button #click="uploadTodos">
Submit
</button>
</div>
This post answers the second part of the question. At first from what I read maatwebsite/excel version 3.0 does not support import. However I am using version 3.1.0 which does support imports. However the method for importing still does not suppport Excel::load(). You should instead use Excel::import() and follow the given rules for passing in parameters. Which of course can be modified to suit your needs. But anyways here is a simple example of how I am using it for anyone interested.
First create import file for whatever model it is. For me it is Todos.
<?php
namespace App\Imports;
use App\Todo;
use Maatwebsite\Excel\Concerns\ToModel;
class TodoImport implements ToModel
{
/**
* #param array $row
*
* #return \Illuminate\Database\Eloquent\Model|null
*/
public function model(array $row)
{
return new Todo([
'user_id' => $row[0],
'todo' => $row[1],
]);
}
}
next you have your controller handling the file, and passing it to the todosimport file
public function importExcel(Request $request)
{
if (empty($request->file('file')->getRealPath())) {
return back()->with('success','No file selected');
}
else {
Excel::import(new TodoImport, $request->file('file'));
return response('Import Succesful, Please Refresh Page');
}
}
notice the Excel::import(). I pass in the new Todo model and the file received.
of course for me since I am doing it by ajax I use this route to ping the method
Route::post('/import', 'TodosController#importExcel');

How to extend a vuejs with a method?

I'm currently trying to wrap my head around how to extend a vuejs instance. Specifically I want to separate an instance, so that I can reuse the base of an instance (the element and the data). I currently have different (laravel/blade) views for adding and editing items (domains), and I want to share a vuejs instance between these two, but I don't want to have the same code (the base) in two places.
Basically, what I'm searching for is the following:
<script type="text/javascript">
var vue = new Vue({
el: '#domain',
data: {
form: {
'name' : '',
'git_repo' : '',
'auto_deploy' : '',
'create_db' : ''
},
ajaxResponse : ''
}
});
</script>
<script type="text/javascript">
Vue.extend('domain_methods', {
methods: {
postDomain: function () {
this.$http.post('{{ route('domain.store') }}', function (data, status, request) {
this.$set('ajaxResponse', data);
}, {
data: this.form
} ).error(function (data, status, request) {
this.$set('ajaxResponse', data);
});
}
}
});
</script>
But that obviously doesn't work. I just want to use the postDomain() method within the #domain element, without the method being written in the initial creation of the instance.
Thanks in advance!
Be careful – you are conflating the usage of .extend() with that of .component(). They do very different things. This section of the docs has more information on the differences:
http://vuejs.org/guide/components.html
In this particular case, just declare your top level Vue class via .extend() and then instantiate a subclass of it by using it as a constructor. This gives you inheritance-like behavior.
So, for instance:
<script type="text/javascript">
var MainVue = Vue.extend({
data: function () {
return {
form: {
'name' : '',
'git_repo' : '',
'auto_deploy' : '',
'create_db' : ''
},
ajaxResponse : ''
};
}
});
</script>
<script type="text/javascript">
var secondary_vue = new MainVue({
el: '#domain',
methods: {
postDomain: function () {
this.$http.post('{{ route('domain.store') }}', function (data, status, request) {
this.$set('ajaxResponse', data);
}, {
data: this.form
} ).error(function (data, status, request) {
this.$set('ajaxResponse', data);
});
}
}
});
</script>

MVC 4 View Knockout Bindings not updating on ajax call

I have gone through as many questions on here as I could find and tried all the different suggestions and cannot get this to work. I have a view that is bound with Knockout using the mapping plugin and it works okay but only when I do the "wrong thing". Everything that I have read says that you should only make one call to ko.applyBindings() per view and then everything should update using ko.mapping.fromJS(). I cannot seem to get this to work, the only way I have been able to get my view to refresh is to call ko.applyBindings() again in the success call back from my .ajax() call. Here is the offending code.
<script type="text/javascript">
var viewModel;
$(document).ready(function() {
$("#panelbar").kendoPanelBar({
expandMode: "multiple"
});
$.ajax({
type: 'GET',
url: '/Home/IsUserMarketingManager',
success: function (data) {
if (data == true) {
$('#submitNewCase').hide();
$('#approveCase').show();
$('#disapproveCase').show();
}
}
});
// Generate client View Model from Server View Model
viewModel = new ViewModel();
ko.mapping.fromJS(#Html.Raw(Json.Encode(Model)),{}, viewModel);
ko.applyBindings(viewModel);
});
function ViewModel () {
var self = this;
self.addLocation = function() {
self.AdditionalLocations.push({ GaNumber: "" });
};
}
</script>
And later this to update the form with retrieved data:
<script type="text/javascript">
$('#btnImport').click(function () {
$.blockUI({ message: '<h2>Importing Client Information...</h2> <img src="/Images/ajax-loader.gif"><br />' });
$.ajax({
type: 'post',
url: '/Home/ImportClientCrmInfoJson',
dataType: "json",
data: ko.mapping.toJS(viewModel),
success: function (data) {
$.unblockUI();
if (!data.AccountNull) {
ko.mapping.fromJS(data, {}, viewModel);
} else {
alert("Could not find account for this GA Number, please try again.");
}
}
});
});
</script>
When submitting the form to my controller, all the data is there and mapped correctly to my server side View Model, but the form in the view isn't updated with the data that comes back from the $.ajax call. I've gotten the form to update if I do the following, but I know it's not the right way and has caused me other issues as well.
<script type="text/javascript">
$('#btnImport').click(function () {
$.blockUI({ message: '<h2>Importing Client Information...</h2> <img src="/Images/ajax-loader.gif"><br />' });
$.ajax({
type: 'post',
url: '/Home/ImportClientCrmInfoJson',
dataType: "json",
data: ko.mapping.toJS(viewModel),
success: function (data) {
$.unblockUI();
if (!data.AccountNull) {
viewModel = ko.mapping.fromJS(data);
ko.applyBindings(viewModel); // This works but isn't the right way...
} else {
alert("Could not find account for this GA Number, please try again.");
}
}
});
});
</script>
Any help would be much appreciated.
Have you examined that the following line of code appears to create a 'NEW' viewmodel?
viewModel = ko.mapping.fromJS(data);
When you do this the new viewModel the old bindings are destroyed. This is why you have to call ApplyBindings again. Anyway, I think the above line of code is the root of the problem.
Is there a way for you to create an observable property on the viewModel and allow the viewModel to reflect the data in this object? That may be a more practical approach to the update process.
In the success callback of the ajax call, use this method ko.applyBindings(viewModel) but pass as a second parameter the DOM portion you want to update as follows
ko.applyBindings(viewModel, $("#mydiv")[0])
Don't use a jquery object but a REAL DOM object.

How to get the load event before ajax call to PHP returns

I would like my webpage to render faster. Based on this article, I understand that the page renders when the 'load' event is fired.
When I look at the Network Tab of my Chrome browser, I see that the 'load' event is fired after an ajax call to a PHP script returns.
Webpage is live at http://www.99like.com/index.php
=> Is there any way to get the page to render before the PHP script is called?
Following is the extract of the code which I think is relevant for the question:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="highcharts.js"></script>
<script type="text/javascript">
var ajax_load = "<img class='loading' src='images/load.gif' alt='loading...' />";
var inputForm = "<div class='shadow'><form type='submit' onsubmit='displayChart(); return false'><input id='searchBox' type='text' size='30' value='search keyword' /></form></div>";
var chart = "<div id='chart' class='shadow'></div>";
var chartPage = inputForm + chart;
$(function ()
{
exampleChart();
});
function exampleChart() {
$('#searchBox').val("hotel"); // nice example
displayChart ();
}
function displayChart () {
var keyword = $('#searchBox').val();
var chart = new Highcharts.Chart({ ... });
chart.showLoading();
var phpFunctionURL = "getChartData.php";
var DataSeries;
$.ajax( {
url: phpFunctionURL,
dataType: 'json',
async: false,
data: { ... },
success: function(json) { DataSeries = json; }
} );
}
</script>
A few remarks:
Make sure all your JavaScript are at the bottom of the page, including JQuery and Google Analytics code
Your web-page is missing the end tag
If needed, you could wait for the onLoad event to launch your AJAX request instead of the DomReady event, this will speed up the page rendering.
Looks like your AJAX request is synchronous. Making it asynchronous will solve the problem.
$.ajax( {
url: phpFunctionURL,
dataType: 'json',
async: true, // Changed from false to true
data: { ... },
success: function(json) { DataSeries = json; }
} );