MVC 4 View Knockout Bindings not updating on ajax call - asp.net-mvc-4

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.

Related

Net Core and JQuery autocomplete

Im having some real problems getting JQuery autocomplete to work in Net Core.
here is my client side script :
<script>
$(document).ready(function () {
$('#txtSystemUserDisplayName').autocomplete({
change: function (event, ui) {
if (!ui.item) {
$('#txtSystemUserDisplayName').val("");
}
},
source: function (request, response) {
$.ajax({
url: "#(Url.Action("SearchEmployeesAJAX", "Home" ))",
// data: "{ 'term': '" + request.term.replace(/'/gi, "\\'") + "'}",
data: { term: 'fumanchu' },
dataType: "json", type: "POST",
contentType: "application/json; charset=utf-8",
success: function (data) {
var x = Array.prototype.slice.call(data);
response($.map(x, function (item) {
return {
label: item.employeeDisplayName,
}
}))
}, error: function (response) { alert(response.responseText); }, failure: function (response) { alert(response.responseText); }
});
},
select: function (e, i) {
$("#hfSystemUserDisplayName").val(i.item.label);
},
minLength: 1
});
});
Now when i start typing , the autocomplete fires but the param in the controller method is NULL , no matter what i do. it doesnt matter what i call the 'term' in the data object of the request. And yes i am making sure that the controller method parameter is named the same . eg
public JsonResult SearchEmployeesAJAX(String term) {
as you can see ive even commented it out and hardcoded a string in there, still null.
it DOES work if I set the string as part of the URL eg:
url: "#(Url.Action("SearchEmployeesAJAX", "Home", new {#term="blahblahblah" }
This is how I have always done autocompletes in the past on .Net Framework, and never had an issue. Is there something different about Net Core that im not aware of, maybe something different about how requests are formed?
Any help would be appreciated.
Ok so if anyone else is also having this problem, it appears that you cant use the Url.Action helper anymore and still have the parameter not be null.
You will need to use a raw string as the url instead, which seemed to solve this.

How to bind the same template multiple times in vue.js?

Submitting a page form results in an ajax call to a backend service which returns an json object. The object is than bound to a vue.js template (a div with a particular id). Everythiong works as expected on the first submit. However, the view is not updated on any following form submits (it still shows the data from the first submit).
<div id="Response"></div>
$('#Form').submit(function (e) {
e.preventDefault();
var $form = $(e.target);
$.ajax({
url: 'https://somewhere,
type: 'POST',
data: $form.serialize(),
dataType: 'json',
success: function(response) {
if (response) {
var app = new Vue({
el: '#Response',
data: response
});
}
}
});
});
How to do this properly so each time the form is submitted, the view is updated appropriately based on the last response?
Now you are creating a new vue instance with each response. You need to mount the vue instance first, then use the response to update the data in it.

Tooltipster not working in a ajax content

While searching in stack overflow .I find an old issue that i am facing too.But no one answered it.
So just wants to know anyone have any idea about it
How to get jquery Tooltipster Plugin to work for newly created DOM elements?
Following is my code
$(document).ready(function() {
$('.test_link').tooltipster({
interactive:true,
content: 'Loading...',
functionBefore: function(origin, continueTooltip) {
continueTooltip();
// next, we want to check if our data has already been cached
//if (origin.data('ajax') !== 'cached') {
$.ajax({
type: 'POST',
url: 'example.php',
success: function(data) {
// update our tooltip content with our returned data and cache it
origin.tooltipster('content', $(data)).data('ajax', 'cached');
}
});
// }
}
});
});
My problem solved.
Just add the instantiation script in the ajax content too.
also set the option multiple:true
ie
$(document).ready(function() {
$('.test_link').tooltipster({
interactive:true,
multiple:true,
content: 'Loading...',
functionBefore: function(origin, continueTooltip) {
continueTooltip();
// next, we want to check if our data has already been cached
//if (origin.data('ajax') !== 'cached') {
$.ajax({
type: 'POST',
url: 'example.php',
success: function(data) {
// update our tooltip content with our returned data and cache it
origin.tooltipster('content', $(data)).data('ajax', 'cached');
}
});
// }
}
});
});
It worked for me in Firefox.But didn't tested in other browser
I know this is an old post, and the problem was solved, but i recently needed something similar.
Adding the initialization on every ajax function was not a solution since we had several content dynamically loaded on the page, so the simplest solution found was:
$(document).on('mouseenter', '[data-toggle="tooltip"]', function(){
if ($(this).is('.tooltipstered')) {
// Do nothing
} else {
$(this).tooltipster({
delay: 50,
// Your other Tooltipster options
});
$(this).mouseover();
}
});
$('[data-toggle="tooltip"]') being the OP's $('.test_link').
The if deter the repeated initialization of document mouseenter.

Kendo UI Mobile Listview always display [object Object]

I'm using Kendo UI Listview control to display Categories data from WCF Service. the problem is always the list view instead of displaying the "Name" of the Category, it display [object Object].
the Json Data returned from the service is like
d
Items
ID=1
Name=Sports
IsActive=true
the HTML code:
<body>
<div data-role="view" data-init="mobileListViewPullWithEndless">
<ul id="grouped-listview"></ul>
</div>
<script>
var categoriesTransport = new kendo.data.RemoteTransport({
read: {
url: "http://localhost:11124/Services/PublishingMobileService.svc/GetAllCategories", //specify the URL which data should return the records. This is the Read method of the Products.svc service.
contentType: "application/json; charset=utf-8", // tells the web service to serialize JSON
dataType: 'json',
type: "POST" //use HTTP POST request as the default GET is not allowed for svc
},
parameterMap: function (data, operation) {
if (operation != "read") {
// web service method parameters need to be send as JSON. The Create, Update and Destroy methods have a "products" parameter.
return JSON.stringify(data);
} else {
return JSON.stringify(data);
}
}
});
function mobileListViewPullWithEndless(e) {
$("#grouped-listview").kendoMobileListView({
height: 400,
dataSource:kendo.data.DataSource.create( {
schema: {
data: "d.Items", // svc services return JSON in the following format { "d": <result> }. Specify how to get the result.
},
transport: categoriesTransport,
template: $("#endless-scrolling-template").text(),
}),
});
}
</script>
<script type="text/x-kendo-tmpl" id="endless-scrolling-template">
<div>
<h3>#:ID#</h3>
</div>
</script>
<script>
var app = new kendo.mobile.Application(document.body);
</script>
Could you please help on that.?
I understand this question is a bit old, but for future reference:
I had this exact issue recently when I bound to an observable without a template. Adding the template as you have gave me the same issue, whereas adding like this works:
<ul id="accomodations-list"
data-role="listview"
data-style="inset"
data-bind="source:accommodations"
data-template="template"></ul>

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; }
} );