Select option data-bind value with knockout - javascript

Hi I have a observable array return from a web API.
1) How to I bind the return jSon as follows to the view model and how do I access it in view?
2) Since there is no information about which option is selected from the returned jSon, how do I make the view initially display the selected option based on the self.selectedAnimal (which is the selected text)?
function NewViewModel() {
var self = this;
self.selectedAnimal = "Cat";
self.GetAnimal() {
$.ajax({
url:"http:/abc.com/api/GetAnimalList",
dataType: "json",
type: "GET",
data: {}
success: function() {
// What to assign here
}
});
}
}
ko.applyBindings(new NewViewModel());
// example of json return
"animals": [
{
"animalid": "1",
"animalname": "cat" },
{
"animalid": "two",
"animalname": "dog" },
{
"animalid": "three",
"animalname": "horse"}
]

Use observableArrays. Like this:
function NewViewModel() {
var self = this;
self.selectedAnimal = ko.observable('Cat');
self.animals = ko.observableArray();
self.getAnimals = function() {
$.ajax({
url:"http:/abc.com/api/GetAnimalList",
dataType: "json",
type: "GET",
data: { }
success: function(animals) {
self.animals(animals);
}
});
};
//reload the animals
//load the view
self.getAnimal();
}
In your view:
<div data-bind="foreach: animals">
<label data-bind="text:animalname"></label>
</div>
Fiddle with example https://jsfiddle.net/vnoqrgxj/

If you have:
<select data-bind="options: animalOptions,
optionsText: 'animalname',
optionsValue: 'animalid',
value: selectedAnimal,
optionsCaption: 'Select animal'">
</select>
As select markup in HTML, then in your view model add the animalOptions array and fill that when the ajax request returns success.
function NewViewModel() {
var self = this;
self.selectedAnimal = "two"; // initial selection as 'dog'
self.animalOptions = ko.observableArray([]);
function GetAnimal() {
$.ajax({
url:"http:/abc.com/api/GetAnimalList",
dataType: "json",
type: "GET",
data: {},
success: function(data) {
// What to assign here
$.each(data.animals, function(i,option){
self.animalOptions.push(option);
});
}
});
}
GetAnimal();
}
ko.applyBindings(new NewViewModel());
For the initially selected option, set self.selectedAnimal = "two" i.e. the animalid value of desired selection.
Read this for more information about options binding.

Related

Storing JSON result from ajax request to a javascript variable for Easyautocomplete

I'm trying to implement the EasyAutoComplete plugin on a field based on the value filled in another field, using ajax requests.
I have a customerid field and when it's value changes, I want the productname field to show all products related to that customerid using the EasyAutoComplete plugin.
Here is what I have so far:
$('#customerid').on('change',function() {
var products2 = {
url: function(phrase) {
return "database/FetchCustomerProducts.php";
},
ajaxSettings: {
dataType: "json",
method: "POST",
data: {
dataType: "json"
}
},
preparePostData: function(data) {
data.phrase = $("#customerid").val();
return data;
},
getValue: "name",
list: {
onSelectItemEvent: function() {
var value = $("#productname").getSelectedItemData().id;
$("#productid").val(value).trigger("change");
},
match: {
enabled: true
}
}
};
$("#productname").easyAutocomplete(products2);
});
Contents of FetchCustomerProducts.php:
if(!empty($_POST["customerid"])){
$products = $app['database']->Select('products', 'customerid', $_POST['customerid']);
echo json_encode(['data' => $products]);
}
However it's not working. The code is based on the 'Ajax POST' example found on this page.
you can using element select category add is class "check_catogory"
after using event click element select get value is option, continue send id to ajax and in file php, you can get $_POST['id'] or $_GET['id'], select find database,after echo json_encode
$("#customerid").change(function(){
var id = $(this).val();
if(id!=""){
$.ajax({
url:"database/FetchCustomerProducts.php",
type:"POST",
data:{id:id},
dataType: "json",
cache:false,
success:function(result){
var options = {
data:result,
getValue: "name",
list: {
onSelectItemEvent: function() {
var value = $("#productname").getSelectedItemData().id;
$("#productid").val(value).trigger("change");
},
match: {
enabled: true
}
}
};
$("#productname").easyAutocomplete(options);
}
})
}
});

Reset (empty) knockout.js select list depending on selection in other select list

I have two select lists, one select list is populated by the selection of the other select list. I have subscribed to the value of the first select box to update the second list every time the value changes. What I am failing to discover is how to reset the second list if a user were to select the default "select ..." option in the first list.
To be clear, the process works, except when a user selects the default options. The Second list keeps the previous selection at that point.
Here's my code (this is an MVC 4 application).
ViewModel:
var DashboardReportViewModel = function (config, originalData) {
var self = this;
self.breweryCode = ko.observable();
self.lineCode = ko.observable();
self.GetBreweries = ko.observableArray([]);
self.GetLines = ko.observableArray([]);
var loadBreweries = function () {
$.ajax({
url: config.GetBreweries,
type: "GET",
error: function (xhr, status, error) {
alert('loadBreweries error');
},
success: function (data) {
self.GetBreweries(data);
},
cache: false
});
};
var loadLines = function () {
$.ajax({
url: config.GetLines,
data: { breweryCode: self.breweryCode() },
cache: false,
type: "GET",
error: function (xhr, status, error) {
alert('loadLines error');
},
success: function (data) {
self.GetLines(data);
}
});
}
loadBreweries();
self.breweryCode.subscribe(function () {
if (self.breweryCode() != undefined) {
loadLines();
}
});
};
View:
<select class="ui-select" id="BrewerySelect" name="BrewerySelect" data-bind="options: GetBreweries,
optionsText: 'Text',
optionsValue: 'Value',
value: breweryCode,
optionsCaption: 'Select a Brewery'"></select>
<select class="ui-select" id="LineSelect" name="LineSelect" data-bind="options: GetLines,
optionsText: 'Text',
optionsValue: 'Value',
value: lineCode,
optionsCaption: 'Select a Line'"></select>
I would go this way:
self.breweryCode.subscribe(function () {
if (!!self.breweryCode()) {
loadLines();
} else {
self.GetLines([]);
}
});
If self.breweryCode() is truthy an Ajax call will be placed to load the lines, otherwise that list is just emptied completely.
PS. If you like you could also use observableArray utility methods to do self.GetLines.removeAll().
You missing else case here:
self.breweryCode.subscribe(function () {
if (self.breweryCode() != undefined) {
loadLines();
}
else {
self.GetLines([]);
}
});

how to pass dynamically created options in multi select box to MVC controller

Please help. I'm using MVC, razor 3, jquery.
I dynamically create a multi select box when a dropdown selection changes. I bind the multiple selection to a List in my model. And it works, except it passes me the list of selected indice, instead of a list of the selected text. I want selected text, not index of the list. I set the value as text, but I have no luck.
if I manually create the list, everything works. How do I pass a list of selected options back to the controller?
I have this div in my view:
<div class="row-fluid" id="divAvailableAssemblies" hidden ="hidden">
<label class="span4">Available Assemblies:</label>
<select multiple="multiple" class="span8 ui-corner-all" id="Request_SelectingAssemblies" name="Request.SelectingAssemblies">
#*<option value="test">test</option>
<option value="test2">test2</option>*#
</select>
</div>
Here my jquery:
<script type="text/javascript">
$(function () {
$('#ddPartsToCreate').live('change',function () {
var selectedPart = this.value;
if (selectedPart < 6 || $("#txtOrderNumber").val()=="")
{
$("#divAvailableAssemblies").attr("hidden", "hidden");
return;
}
$("#divAvailableAssemblies").removeAttr("hidden");
$.ajax({
type: 'POST',
url: '#Url.Action("GetSelectingAssembliesFromOrder", "Home")',
data: JSON.stringify({ orderNumber: $("#txtOrderNumber").val() }),
dataType: 'json',
contentType: 'application/json; charset=utf-8',
cache: false,
async: false,
success: function (response) {
var returnedData = JSON.parse(response);
var selectingAssemblies = $("#Request_SelectingAssemblies");
selectingAssemblies.empty();
for (var assembly in returnedData)
{
//selectingAssemblies.append($('<option >', { value: assembly }).text(returnedData[assembly].Text)).hide().show();
//selectingAssemblies.append($('<option value=' + assembly + '>' + returnedData[assembly].Text + '</option>'));
//selectingAssemblies.append($('<option >', { value: assembly, text: returnedData[assembly].Text }));
//selectingAssemblies.append($('<option></option>').val(assembly).html(returnedData[assembly].Text));
//$("#Request_SelectingAssemblies").append($('<option>', { value: assembly }).text(returnedData[assembly].Text));
//$("#Request_SelectingAssemblies").append($('<option>', { value: assembly }).text(returnedData[assembly].Text));
//$('<option />', { value: assembly, text: returnedData[assembly].Text }).appendTo(selectingAssemblies);
selectingAssemblies.append($('<option></option>').val(assembly).html(returnedData[assembly].Text));
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert(errorThrown);
}
});
});
});
in the backend, I generate JSON:
foreach (var assembly in pr.ShipParts)
{
sb.Append(String.Format(",{{\"Text\":\"{0}\", \"Value\":\"{1}\"}}", assembly.Mark.ToString(), assembly.Mark.ToString()));
availableAssemblies.Add(assembly.Mark.ToString());
}
I bind the multiple selection(Request_SelectingAssemblies) with this property in my model:
public List<String> SelectingAssemblies
{
get
{
return _SelectingAssemblies;
}
set
{
_SelectingAssemblies = value;
}
}
private List<String> _SelectingAssemblies = new List<string>();
When it gets to my action in the controller, SelectingAssemblies has index instead of the actual text. But I set the value of each option as text. If I set the option manually, they will show in source page and return the text. But since I dynamically create the options, they don't show in source page. I don't know how I can make MVC understand dynamic data.
In the picture, the list of CX001, RBX001, RBX002 is dynamically created. if I hit F12 in IE, I will see them created correctly in the DOM. If I choose CX001 and RBX002, SelectionAssembies will have 0 and 2.
Thanks
This is the latest and working code, thanks to #StephenMuecke:
<script type="text/javascript">
$(function () {
$('#ddPartsToCreate').live('change',function () {
var selectedPart = this.value;
if (selectedPart < 6 || $("#txtOrderNumber").val()=="")
{
$("#divAvailableAssemblies").attr("hidden", "hidden");
return;
}
$("#divAvailableAssemblies").removeAttr("hidden");
$.ajax({
type: 'POST',
url: '#Url.Action("GetSelectingAssembliesFromOrder", "Home")',
data: JSON.stringify({ orderNumber: $("#txtOrderNumber").val() }),
dataType: 'json',
contentType: 'application/json; charset=utf-8',
cache: false,
async: false,
success: function (response) {
var returnedData = JSON.parse(response);
var selectingAssemblies = $("#Request_SelectingAssemblies");
$.each(returnedData, function (index, item) {
selectingAssemblies.append($('<option></option>').val(item.Value).html(item.Text));
});
},
error: function (jqXHR, textStatus, errorThrown) {
alert(errorThrown);
}
});
});
});
public ActionResult GetSelectingAssembliesFromOrder(String orderNumber)
{
return Json(model.GetSelectingAssembliesFromOrder(orderNumber), JsonRequestBehavior.AllowGet);
}
public String GetSelectingAssembliesFromOrder(String orderNumber)
{
//...
StringBuilder sb = new StringBuilder();
sb.Append("[");
foreach (var assembly in pr.ShipParts)
{
string assemblyName = assembly.Mark.Trim();
sb.Append(String.Format(",{{\"Text\":\"{0}\", \"Value\":\"{1}\"}}", assemblyName, assemblyName));//JSON to build the list
//...
}
sb.Append("]");
sb.Remove(1, 1);//remove extra comma
_db.SaveChanges();
return sb.ToString();
}

Set selected value on select2 without loosing ajax

I have this select2 code in my html (mvc with razor) page:
$('#QuickSearchState').select2({
minimumInputLength: 3,
width: 'resolve',
ajax: {
url: '#Url.Action("QuickSearchState", "DataCenter")',
contentType: 'application/json',
dataType: 'json',
type: 'POST',
traditional: true,
quietMillis: 400,
data: function(term, page) {
var data = {
term: term
};
return data;
},
results: function(data, page) {
return { results: data };
}
},
initSelection: function(element, callback) {
var data = { id: element.val(), text: element.val() };
callback(data);
},
formatResult: function(format) {
return format.label;
},
formatSelection: function(format) {
//this is a knockout view model
vmNewAddress.IdState(format.id);
vmNewAddress.StateName(format.stateName);
return format.label;
},
dropdownCssClass: "bigdrop",
escapeMarkup: function(m) { return m; }
});
But i have another select in my code that can set a state in this select, but i dont know how to set this value to that select.
In my html i have this:
<select class="width-xl" data-bind="options: vm.GivenLocationsForConnection, optionsText: 'DisplayFormat', value: SelectedLocation"></select> -> first select that can fill the second state search select with a state
#Html.Hidden("query", null, new { #id = "QuickSearchState", #class = "width-xl", placeholder = "Ej. Montevideo" }) -> second select, this is a search for states and selects a single state
I am not sure if this is what you want but if you only want to select a value in the select you can just do below
$("#QuickSearchState").select2("val", "<YOUR VALUE>");

how do I use dynamic controls with knockoutjs

I have a scenario that I'm attempting to apply knockout to with some problems. Basically I have this sort of ui
Add (create a new Select Box duo with delete button)
Select Box (options = Json from ajax request)
Select Box (options = Json from ajax request with param from 1st select)
Delete
Select Box
Select Box
Delete
etc
Each row I regard as another Widget in the array so my knockout for simplicity
var ViewModel = function (widgets) {
var self = this;
this.widgets= ko.observableArray(widgets);
this.subWidgets= ko.observableArray();
this.mySelections = ko.observableArray();
this.selectedWidget.subscribe(function (name) {
if (name != null) {
$.ajax({
url: '#Url.Action("AddSubWidgetsByName")',
data: { name: name },
type: 'GET',
async: false,
contentType: 'application/json',
success: function (result) {
self.subWidgets(result);
}
});
}
} .bind(this));
self.addWidget = function (widget) {
self.mySelections.push({
??? profit
});
};
}
var viewiewModel = new ViewModel();
ko.applyBindings(viewiewModel);
$.ajax({
url: '#Url.Action("AddFund")',
type: 'GET',
async: false,
contentType: 'application/json',
success: function (result) {
viewModel.widgets(result);
}
});
<select id="widgets"
data-bind='
options: widgets,
optionsValue : "Name",
optionsText: "Name",
optionsCaption: "[Please select a widgets]"'
value: selectedWidget,
>
Can I dynamically create a select for each widget and relate the subwidget selection to an item in mySelections array? I can't use the value binding for selectedWidget in quite this way as all dropdowns are bound together in this manner. I need to make them independant - any ideas on how to go about that?
Cheers!
One way of doing this is to make each widget its own viewmodel (note, this is from jsFiddle, so the ajax is done to work with their echo API, which requires POST):
var Widget = function(){
var self = this;
self.selectedWidget = ko.observable('');
self.subWidgets = ko.observableArray([]);
self.selectedSubWidget = ko.observable('');
this.selectedWidget.subscribe(function (name) {
if (name != null) {
$.ajax({
url:"/echo/json/",
data: {
json: $.toJSON(
[Math.floor(Math.random()*11),
Math.floor(Math.random()*11),
Math.floor(Math.random()*11)]
),
delay: 1
},
type:"POST",
success:function(response)
{
self.subWidgets(response);
}
});
}
});
};
You could then easily track sub-selections and additions with a simple viewmodel. Here is the complete fiddle.

Categories

Resources