Knockout ViewModel Update - c#

I am new to Knockout and I am trying to update my ViewModel from an ajax call. This is what I have right now:
LoanDeductions.js
var deductionLine = function (deductionID, deductionName, amount) {
self = this;
self.deductionID = ko.observable(deductionID);
self.deductionName = ko.observable(deductionName);
self.amount = ko.observable(amount);
};
function LoanDeductions(deductions) {
var self = this;
self.loanDeductions = ko.observableArray(ko.utils.arrayMap(deductions, function (deduction) {
return new deductionLine(deduction.deductionID, deduction.deductionName, deduction.amount)
}));
// Operationss
self.removeLine = function (line) { self.loanDeductions.remove(line) };
};
and this is my scripts in my view:
#section scripts
{
<script src="~/Scripts/koModel/LoanDeductions.js"></script>
<script type="text/javascript">
var updateValues = function () {
$.ajax({
'url': '#Url.Action("UpdateDeductionValues","LoanApp")',
'data': { amount: $('.LoanAmount').val() },
'success': function (result) {// update viewmodel scripts here}
});
var viewModel = new LoanDeductions(#Html.Raw(Model.CRefLoansDeductions2.ToJson()));
$(document).ready(function () {
ko.applyBindings(viewModel);
$('.datepicker').datepicker();
$('.LoanAmount').change(function () {
updateValues();
};
});
});
</script>
}
So, in my view, I have a dropdown list with class name "LoanAmount" which when value is changed, it will perform an ajax call, send the selected loanAmount value to the server, recompute the deduction amounts, then the server returns a jsonresult that looks like this:
"[{\"deductionID\":1,\"deductionName\":\"Loan Redemption Fee\",\"amount\":53.10},{\"deductionID\":2,\"deductionName\":\"Document Stamp\",\"amount\":9.00}]"
Now what I wanted to do is use this json data as my new viewModel.
Can anyone show me the way how to do this, please note that I manually mapped my viewmodel and didn't used the ko mapping plugin.
Any help will be greatly appreciated. Thank you, more power!
EDIT (in response to Fabio)
function updateData() {
$.ajax({
url: '#Url.Action("UpdateDeductionValues","LoanApp")',
data: { amount: self.selectedLoanAmount() },
success: function (deductions) {
//load your array with ko.utils.arrayMap
ko.utils.arrayMap(deductions, function (deduction) {
return new deductionLine(deduction.deductionID, deduction.deductionName, deduction.amount)
});
}
});
}

Not sure If I understood your problem, but if you want to change model values outside of the class, you need to do something like this:
$(document).ready(function () {
var viewModel = new LoanDeductions(#Html.Raw(Model.CRefLoansDeductions2.ToJson()));
ko.applyBindings(viewModel);
$('.datepicker').datepicker();
function updateValues() {
//do you ajax call
//update the model using viewModel.loanDeductions(newItens);
};
$('.LoanAmount').change(function () {
updateValues();
};
});
EDIT 1 - Just to show how to use knockout without jquery.change
function LoadDeductions() {
//declare you properties
var self = this;
self.loanAmount = ko.observable('initialvalueofloanamount');
self.loanDeductions = ko.observableArray();
//create a function to update you observablearray
function updateData() {
$.ajax({
url: '#Url.Content('yourActionhere')' or '#Url.Action('a', 'b')',
data: { amount: self.loadAmount() },
success: function (deductions) {
//load your array with ko.utils.arrayMap
}
});
}
//everytime that loanAmount changes, update the array
self.loanAmount.subscribe(function () {
updateData();
});
//update values initializing
updateData();
};
$(function() {
ko.applyBindings(new LoadDeductions());
});
Bind the select in the HTML
<select data-bind="value: loanAmount"></select>
EDIT 2 - To your second problem
function updateData() {
$.ajax({
url: '/LoanApp/UpdateDeductionValues', //try to write the url like this
data: { amount: self.selectedLoanAmount() },
success: function (deductions) {
//load your array with ko.utils.arrayMap
self.loanDeductions(ko.utils.arrayMap(deductions, function (deduction) {
return new deductionLine(deduction.deductionID, deduction.deductionName, deduction.amount)
}));
}
});
}

Your success handler should look like this.
function(result){
self.loanDeductions(result);
}
Unless you are trying to append in which case it would be
self.loanDeductions(self.loanDeductions().concat(result));

Related

Update C# variable via Ajax?

I have got a page full of posts, I sort those posts before rendering it.
Now I have created a drop down so user's can sort the posts by newest or oldest.
The only problem is I don't know how to update the server-side variable through Ajax.
#{
var SortSelected = "";
var sortedArticles = ListOfPosts.OrderBy(x => x.GetPropertyValue<DateTime>("articleDate")).Reverse().ToList();
if (SortSelected == "Most recent")
{
sortedArticles = ListOfPosts.OrderBy(x => x.GetPropertyValue<DateTime>("articleDate")).Reverse().ToList();
}
else if (SortSelected == "Oldest")
{
sortedArticles = ListOfPosts.OrderBy(x => x.GetPropertyValue<DateTime>("articleDate")).ToList();
}
}
I have removed other code which is irrelevant to make it cleaner.
That's my code for the posts, this is the Razor(html)
<div class="AnimatedLabel">
<select name="contact" class="tm-md-12">
<option id="hide-selector-dropdown" value=""></option>
#foreach (var item in FilterTypes)
{
<option value="#item">#item</option>
}
</select>
<label for="contact">Sort by</label>
<span class="tm-icon-arrow--right" id="selector-dropdown-arrow"></span>
</div>
This is how I tried to do it -
<script>
$('select').on('change', function () {
SortSelected = this.value;
});
</script>
But it is not updating the value, I have been told because it is server-side.
I know people will probably roast me for this question but I do not know any other solution so any help would be great!
I do not have much experience with .net/c#
Thanks!
Okay, so I just wanted to show you how you can achieve something like this using AJAX. As far as I have understood, you want to sort your posts list based on the selection from the user in the dropdown list that you have. Please refer to the code snippet below and let me know if you were able to get what you wanted regarding your requirement:
<script>
$('select').on('change', function () {
//SortSelected = this.value;
//First get the text of the selected item
var selectedText=$('#hide-selector-dropdown :selected').text();
//Now generate your JSON data here to be sent to the server
var json = {
selectedText: selectedText
};
//Send the JSON data via AJAX to your Controller method
$.ajax({
url: '#Url.Action("ProcessMyValue", "Home")',
type: 'post',
dataType: "json",
data: { "json": JSON.stringify(json)},
success: function (result) {
//Show your list here
if (data.success) {
console.log(data.sortedArticles);
}
else {
console.log("List empty or not found");
}
},
error: function (error) {
console.log(error)
}
});
});
</script>
Your Controller would look like:
using System.Web.Script.Serialization;
[HttpPost]
public ActionResult ProcessMyValue(string json)
{
var serializer = new JavaScriptSerializer();
dynamic jsondata = serializer.Deserialize(json, typeof(object));
//Get your variables here from AJAX call
var SortSelected= jsondata["selectedText"];
//Do something with your variables here. I am assuming this:
var sortedArticles = ListOfPosts.OrderBy(x => x.GetPropertyValue<DateTime>("articleDate")).Reverse().ToList();
if (SortSelected == "Most recent")
{
sortedArticles = ListOfPosts.OrderBy(x => x.GetPropertyValue<DateTime>("articleDate")).Reverse().ToList();
}
else if (SortSelected == "Oldest")
{
sortedArticles = ListOfPosts.OrderBy(x => x.GetPropertyValue<DateTime>("articleDate")).ToList();
}
return Json(new { success = true, sortedArticles }, JsonRequestBehavior.AllowGet);
}
You can't change server variable value but you can use this for refresh your table.
<script>
$('select').on('change', function () {
$.get('/Url' , {sortBy:this.value}).done(function(result){
$('#yourTable').html(result);
}).fail(function(){
alert('Error !');
});
});
</script>
You can call web method in server side using ajax.
Use that method to update variable on server side

Use jQuery Select2 with ASP.NET MVC

I'm trying to use Select2 in Razor in ASP.NET MVC. But I can't get work.
$(document).ready(function () {
$(".genreOptions").select2({
tags: true,
ajax: {
url: 'http://localhost:65148/NewProfile/Genres',
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term, // search term
page: params.page
};
},
processResults: function (data, page) {
var newData = [];
$.each(data, function (index, item) {
newData.push({
id: item.Id, //id part present in data
text: item.Genre //string to be displayed
});
});
return { results: newData };
},
cache: true
},
escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
minimumInputLength: 1
});
#Html.DropDownListFor(x => x.BandProfile.Genres, Enumerable.Empty<SelectListItem>(), new { #class="genreOptions", multiple = "multiple", style ="width: 100%;"} )
The searching for tags works fine. But when I post the form, the count of the input field Is 0. How can I capture the data from the input form?
#Bryan I build up a javascript array and pass it with ajax to the server. Seems to work ok for my purposes. Perhaps you could try that. The selectors I put below will be different than what you need but here is the general idea...
On Click
$('#submitButton').click(function () {
fillHiddenInput();
var dataToSend = $('#hiddenInput').val();
//Submit the form with ajax or however you want to get dataToSend to server
});
FillHiddenInput function...
var fillHiddenInput = function () {
$('#hiddenInput').val("");
var stuff = [];
$('.ms-selection .ms-list li ul').children('li').each(function (){
if ($(this).hasClass('ms-selected'))
{
stuff.push($(this).children('span').text());
}
});
$('#hiddenInput').val(stuff);
}

jQuery autocomplete rendering results that are hidden

I'm trying to use the autocomplete widget in jQuery however when I start typing nothing shows up below it. I can tell it's doing something becasue as I type I can see the scroll bar on the page changing as the list gets shorter, but I can't see the results. My code is below. Any help is appreciated with this.
My controller method looks like this:
public ActionResult GetUsers(string query)
{
var empName = from u in HomeModel.CombineNames()
where u.StartsWith(query)
select u.Distinct().ToArray();
return Json(empName);
}
My View looks like this:
<script type="text/javascript">
$(document).ready(function() {
$("input#autocomplete").autocomplete({
source: function(request, response) {
$.ajax({
url: '/Home/GetUsers',
type: "POST",
dataType: "json",
data: { query: request.term },
success: function(data) {
response($.map(data, function(item) {
return { label: item, value: item };
}));
}
});
}
});
})
</script>
<input type="text" id = "autocomplete"/>
You are missing a few things, like render item, cache managment.
the code should looks something like this: (assuming your action return an array of string)
var cache = {},lastXhr;
$( "input#autocomplete" ).autocomplete({
minLength: 4,
source: function (request, response) {
var term = request.term;
if (term in cache) {
response(cache[term]);
return;
}
var descripcion = new Array();
peticion = $.getJSON('/Home/GetUsers',{ query: request.term }, function (data, status, xhr) {
for (d in data) {
descripcion.push(data[d]);
}
cache[term] = descripcion;
if (xhr === peticion) {
response(descripcion);
}
});
},
select: function( event, ui ) {
$("input#autocomplete" ).val( ui.item);
return false;
}
})
.data( "autocomplete" )._renderItem = function( ul, item ) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + item + " </a>" )
.appendTo( ul );
};
Try using the inspection tools of your browser to examine the area where your scroll bar is changing. If the elements are present, you likely need to make some changes to the CSS so your text color is different from the background color (or some other display-related issue).

JQuery Autocomplete loading data from model in aspx page

I am trying to
1) create a JQuery AutoComplete box that is populated from an aspx method, and
2)once I get the results, I wish to populate these results inside a list.
At the moment I am trying to do step one however without my success.
My code is as follows:-
ASPX
<script>
$(function () {
$("#persons").autocomplete({
//source: availableTags
source: function (request, response) {
var term = request.term;
var personArray = new Array();
$.post('JQAutoComplete.aspx/FetchPersonList', { personName: term }, function (persons) {
personArray = persons;
alert('PersonArray' - personArray);
alert('Persons' - persons);
response(personArray);
});
}
});
});
<div class="ui-widget">
<label for="persons">Persons: </label>
<input id="persons" />
</div>
</body>
and my aspx.cs is as follows :-
public JsonResult FetchPersonList(string personName)
{
var persons = ctx.GetDataFromXML(false, 0);
return (persons) as JsonResult;
}
*************UPDATE ASPX.CS*******************
ok so I changed the method to this:-
[WebMethod]
public static List<Person> FetchPersonList()
{
//var persons = this.HouseService.SelectByName(houseName).Select(e => new String(e.Name.ToCharArray())).ToArray();
var persons = ctx.GetDataFromXML(false, 0);
return (List<Person>) persons;
}
but I am still not getting through the method!
However the code is not hitting this method at all.
How can I get this list?
Thanks for your help and time
Ok I found the problem.
I changed my JQuery to the following and its calling the method now :-
$(document).ready(function () {
SearchText();
});
function SearchText() {
$("#persons").autocomplete({
source: function (request, response) {
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "JQAutoComplete2.aspx/FetchPersons",
data: "{'name':'" + document.getElementById('persons').value + "'}",
dataType: "json",
success: function (data) {
response(data.d);
alert(data.d);
},
error: function (result) {
alert("Error");
}
});
}
});
}
and my ASPX.CS looks like this :-
[WebMethod]
public static List<Person> FetchPersons(string name)
{
var persons = ctx.GetDataFromXML(false, 0);
return (List<Person>)persons;
}

using jquery to send a dropdownbox value to a controller and filling another dropdown box with the results

I know there are already a few posts on this subject but I cannot seem to figure out an answer to my specific issue. I am confused as to why I cannot pass a variable into the controller but I can pass in a hardcoded value...
This works...
<script type="text/javascript">
$().ready(function () {
$("#MessageTypes").change(function () {
//I know this is a horrible way to do it but for some reason I couldnt pass the sMessageType directly in
var sMessageType = $("#MessageTypes").val();
if (sMessageType == "Professional Voicefile") {
$.get('#Url.Action("GenerateMessageDesc", new { MessageType = "Professional Voicefile" } )', function (data) {
$('#MessageDesc').replaceWith(data);
});
}
else if (sMessageType == "Dynamic Field") {
$.get('#Url.Action("GenerateMessageDesc", new { MessageType = "Dynamic Field" } )', function (data) {
$('#MessageDesc').replaceWith(data);
});
}
else {
//default to prof
$.get('#Url.Action("GenerateMessageDesc", new { MessageType = "Professional Voicefile" } )', function (data) {
$('#MessageDesc').replaceWith(data);
});
}
});
});
...But this does not. Why?
<script type="text/javascript">
$().ready(function () {
$("#MessageTypes").change(function () {
var sMessageType = $("#MessageTypes").val();
$.get('#Url.Action("GenerateMessageDesc", new { MessageType = sMessageType } )', function (data) {
$('#MessageDesc').replaceWith(data);
});
}
});
});
It says "The name 'sMessageType' does not exist in the current context".
I think maybe I should be using some kind of ajax call instead to call the controller and update the view instead of how I am doing it -- however, why does scenario 1 work but not scenario 2?
It says "The name 'sMessageType' does not exist in the current context".
sMessageType is a javascript variable that lives on the client that you are trying to use inside a server side helper. That obviously is impossible because javascript runs on the client and server side script on the server.
Here's the correct way to achieve that:
$.get('#Url.Action("GenerateMessageDesc")', { messageType: sMessageType }, function (data) {
$('#MessageDesc').replaceWith(data);
});
this will pass the MessageType as query string parameter, so your target controller action might look like this:
public ActionResult GenerateMessageDesc(string messageType)
{
...
}

Categories