knockoutjs select option not bind - asp.net-mvc

I am very new to knockoutjs. I try to modified a little from [knockoutjs sample] (http://knockoutjs.com/documentation/options-binding.html) but it didn't work.
<select data-bind="option: availCustomers, optionsText: 'CustomerName',
value: selectedCustomer, optionsCaption: '--- Choose ---'">
</select>
and the viewmodel :
<script>
function customerViewModel() {
var self = this;
self.availCustomers = ko.observableArray();
self.selectedCustomer = ko.observable();
};
var Customer = function (id, name) {
this.CustomerId = id;
this.CustomerName = name;
};
$(document).ready( function() {
var cvm = new customerViewModel();
cvm.availCustomers = new ko.observableArray([
new Customer("12345", "ABC"),
new Customer("54321", "XYZ")
]);
ko.applyBindings(cvm);
});
</script>
so please guide me

I think this is just a mispeling error, the parameter to bind is called "options".
<select data-bind="options: availCustomers, optionsText: 'CustomerName',
value: selectedCustomer, optionsCaption: '--- Choose ---'">
</select>

Related

Validate input field on submit

Im tryinf to validate this input field when i click on Submit button. What happens is when I click on the submit button and the textbox is empty it alert thank you,however it should alert Please check your submission
Html
<div id="newTest">
<fieldset>
<div class="row">
<label>Last name:</label>
<input type="text" data-bind="value: lastName" />
</div>
</fieldset>
<fieldset>
<button type="button" data-bind='click: submit'>Submit</button>
</fieldset>
</div>
Javascript
<script src="~/Scripts/knockout-3.5.0.js"></script>
<script src="~/Scripts/knockout.validation.min.js"></script>
<script>
var viewModel = function () {
ko.validation.rules.pattern.message = 'Invalid.';
ko.validation.init({
registerExtenders: true,
messagesOnModified: true,
insertMessages: true,
parseInputAttributes: true,
messageTemplate: null
}, true);
var self = this;
self.lastName = ko.observable().extend({ required: true }),
self.submit = function () {
if (viewModel.errors().length === 0) {
alert('Thank you.');
}
else {
alert('Please check your submission.');
viewModel.errors.showAllMessages();
}
};
};
viewModel.errors = ko.validation.group(viewModel);
var viewModel2 = new viewModel();
ko.applyBindings(viewModel2, document.getElementById("newTest"));
</script>
Since you are initializing viewModel2 as new viewModel(), these two lines of code:
viewModel.errors = ko.validation.group(viewModel);
var viewModel2 = new viewModel();
should be:
var viewModel2 = new viewModel();
viewModel.errors = ko.validation.group(viewModel2);
It's also unclear to me why you wrote this the way you did. It could be simpler IMO. Here's an example (JSFiddle: https://jsfiddle.net/vwuazfg0/):
ko.validation.rules.pattern.message = 'Invalid.';
ko.validation.init({
registerExtenders: true,
messagesOnModified: true,
insertMessages: true,
parseInputAttributes: true,
messageTemplate: null
}, true);
var viewModel = {
lastName : ko.observable().extend({ required: true }),
submit : function () {
if (viewModel.errors().length === 0) {
alert('Thank you.');
}
else {
alert('Please check your submission.');
viewModel.errors.showAllMessages();
}
}
};
viewModel.errors = ko.validation.group(viewModel);
ko.applyBindings(viewModel, document.getElementById("newTest"));

bootstrap Dual Listbox knockout binding

I am using bootstrap dual listbox pluging in my ASP.NET MVC project.
I am also using Knockout in the project. I am trying to create bindingHandler for the this plugin to make it working smoothly with knockout.
here is what I tried
Binding Handler
ko.bindingHandlers.dualList = {
init: function (element, valueAccessor) {
$(element).bootstrapDualListbox({
selectorMinimalHeight: 160
});
$(element).on('change', function () {
$(element).bootstrapDualListbox('refresh', true);
});
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).bootstrapDualListbox('destroy');
});
},
update: function (element, valueAccessor) {
$(element).bootstrapDualListbox('refresh', true);
}
}
HTML
<select class="form-control" data-bind="foreach:{data: EditedElement().Operations, as : 'op'} , dualList: EditedElement().Operations" multiple>
<option data-bind="value: op.OperationID(), text: op.Name(), selected: op.IsSelected()"></option>
</select>
View Model
function SelectOperationVM(operationId, isSelected, name) {
var self = this;
self.OperationID = ko.observable(operationId);
self.IsSelected = ko.observable(isSelected);
self.Name = ko.observable(name);
self.copy = function () {
return new SelectOperationVM(self.OperationID(), self.IsSelected(), self.Name());
}
}
My problem is that I can not make sync between the viewModel observableArray, and the plugin.
In other words, I want the changes in the plugin (the user removed some options or added some options) to be reflected on the view model property, and vice verse
to sync, you need to pass multiple observables to custom binding
so your html should be like
<select class="form-control" data-bind="foreach: { data: Operations, as: 'op'}, dualList: { options: Operations, selected: Selected }" multiple>
<option data-bind="value: op.OperationID(), text: op.Name(), selected: op.IsSelected()"></option>
</select>
and custom binding be like
ko.bindingHandlers.dualList = {
init: function(element, valueAccessor) {
var data = ko.utils.unwrapObservable(valueAccessor());
$(element).bootstrapDualListbox({
selectorMinimalHeight: 160
});
$(element).on('change', function() {
// save selected to an observable
data.selected($(element).val());;
});
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$(element).bootstrapDualListbox('destroy');
});
},
update: function(element, valueAccessor) {
// to view if there is an update (without this "update" will not fire)
var options = ko.utils.unwrapObservable(valueAccessor()).options();
$(element).bootstrapDualListbox('refresh', true);
}
}
also i have created a dirty working jsfiddle

knockout js - access variable inside object

I am trying to create a computed variable (RateDisplay) based on what the user enters(MinRate, MaxRate if VRAChecked is true, else FlatRate) that is defined as an observable. I have an object (product) as part of the viewmodel like the following:
var viewModel = new function () {
var self = this;
self.Id = ko.observable();
self.product = {
Id: ko.observable(),
Name: ko.observable(),
VRAChecked: ko.observable(false),
MinRate: ko.observable(),
MaxRate: ko.observable(),
FlatRate: ko.observable(),
RateDisplay: ko.computed(function() {
if (self.product.VRAChecked())
{
return self.product.MinRate() + "-" + self.product.MaxRate();
}
else
{
return self.product.FlatRate();
}
}, this),
PercentageGoal: ko.observable()
};
};//viewmodel ends
The problem is, I get this js error: "self.product is undefined" at the line
if (self.product.VRAChecked())
I understand that, that is probably because the object is still being created.
So, how do I create the computed variable (RateDisplay)? I need it to be an element of that object (product).
The problem is that you're creating the computed before the other product properties are even created, and then, they are not defined yet.
Try to create it only after the product declaration, and it will work like a charm.
Take a look at the example below:
var viewModel = function() {
var self = this;
self.Id = ko.observable();
self.product = {
Id: ko.observable(),
Name: ko.observable(),
VRAChecked: ko.observable(false),
MinRate: ko.observable(),
MaxRate: ko.observable(),
FlatRate: ko.observable(),
PercentageGoal: ko.observable()
};
self.product.RateDisplay = ko.computed(function() {
if (self.product.VRAChecked()) {
return self.product.MinRate() + "-" + this.product.MaxRate();
} else {
return self.product.FlatRate();
}
}, self)
}
ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div>
<label>Min Rate <input type="textbox" data-bind="value: product.MinRate"></label>
<label>Max Rate <input type="textbox" data-bind="value: product.MaxRate"></label>
</div>
<div>
<label>Flat Rate <input type="textbox" data-bind="value: product.FlatRate"></label>
</div>
<div>
<label><input type="checkbox" data-bind="checked: product.VRAChecked"> VRA Checked</label>
</div>
<div>Display: <span data-bind="text: product.RateDisplay"></span></div>

How to determiine which dropdown was used

I have a form with more than one dropdown list, like this below. I can see how to get the ID's of each dropdown but I can't figure out how to get the one that was actually used. Would someone explain how to do that, please.
<div>
<select name="id[11]" class="pullDown" id="attrdrop0">
<option class="pink" value="31`">No</option>
<option class="pink" value="32">Yes (+$40.00)</option>
</select>
</div>
<div>
<select name="id[10]" class="pullDown" id="attrdrop1">
<option class="pink" value="31">No</option>
<option class="pink" value="32">Yes (+$150.00)</option>
</select>
</div>
<script>
$(function () {
$("#prices").change(function () {
console.log('A change was made');
CalculatePrice();
});
});
function CalculatePrice() {
var ttl_price = 0;
var id = '';
$(":input.select, :input").each(function() {
var cur_price = $('option:selected', $(this)).text();
ttl_price += cur_price;
id = $(this).attr('id');
/*** What now ***/
});
SetPrice(id, ttl_price);
}
</script>
You can pass the control as a parameter to CalculatePrice.
$(function () {
$("#prices").change(function () {
console.log('A change was made');
CalculatePrice(this);
});
});
function CalculatePrice(triggerObject) {
var ttl_price = 0;
var id = '';
$(":input.select, :input").each(function() {
var cur_price = $('option:selected', $(this)).text();
ttl_price += cur_price;
id = $(this).attr('id');
/*** What now ***/
if (triggerObject.id) {...}
});
SetPrice(id, ttl_price);
}
</script>

Knockout computed only firing once [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have a feeling that this isn't going to be a simple problem (or may be associated with something entirely un-related) but I'm going to take a shot. I have an ASP.NET MVC page that also uses KnockOutJS. There are two related drop-downs on the page. The first one presents a list of Offer Types. Depending on which Offer Type you choose, the second drop-down needs to re-populate with the correct options for that Offer Type.
This used to work at some point in time, but the page is under heavy construction and now not working. When I select a new Offer Type, the other dropdown doesn't repopulate.
Here is the HTML for the DropDowns. You'll notice there is a hidden input there. When I select a new OfferType, this correctly populates with the OfferTypeId.
<div class="control-group" style="clear: both;">
#Html.LabelFor(m => m.OfferType, new { #class = "control-label" })
<div class="controls">
<select class="input-block-level" id="OfferType" name="OfferType" data-bind="options: offerTypes, value: selectedOfferType, optionsText: 'DisplayName'"></select>
</div>#Html.HiddenFor(m => m.OfferTypeId, new { data_bind = "value: selectedOfferType().OfferTypeId" })
</div>
<div class="control-group" style="clear: both;">
#Html.LabelFor(m => m.OfferTypeDetails, new { #class = "control-label" })
<div class="controls">
<select class="input-block-level" id="OfferTypeDetails" name="OfferTypeDetails" data-bind="options: offerDetails, value: selectedOffer, optionsText: 'DisplayName'"></select>
</div>#Html.HiddenFor(m => m.OfferTypeDetailsTypeId, new { data_bind = "value: selectedOffer().OfferTypeId" })
</div>
And here is the Javascript (data trimmed for brevity):
$(document).ready(function () {
var offerType = function (offerTypeId, displayName, offerTypeDetailsTypes) {
var self = this;
self.OfferTypeId = offerTypeId;
self.DisplayName = displayName;
self.OfferTypeDetailsTypes = offerTypeDetailsTypes;
};
var offerTypeDetailsType = function (offerTypeDetailsTypeId, displayName, offerTypeId) {
var self = this;
self.OfferTypeDetailsTypeId = offerTypeDetailsTypeId;
self.DisplayName = displayName;
self.OfferTypeId = offerTypeId;
};
function viewModel() {
var self = this;
self.selectedOfferType = ko.observable();
self.selectedOffer = ko.observable();
self.offerTypes = ko.observableArray([
new offerType('1', 'Purchase Discount'),
new offerType('2', 'Savings'),
...
]);
self.offerTypeDetailsTypes = ko.observableArray([
new offerTypeDetailsType('1', 'Spend $10 Get $1 Off', '1'),
new offerTypeDetailsType('2', 'Spend $100 Get 10% Off', '1'),
new offerTypeDetailsType('3', '$ Half Off', '2'),
...
]);
self.offerDetails = ko.computed({
read: function () {
var activeCategories = ko.observableArray();
ko.utils.arrayForEach(self.offerTypeDetailsTypes(), function (item) {
if (item.OfferTypeId == self.selectedOfferType().OfferTypeId)
activeCategories.push(item);
});
return activeCategories();
} , deferEvaluation: true
});
}
ko.applyBindings(new viewModel());
}
Todd, I was able to get your example code working without any problems. I just coppied to jsFiddle and remove the MVC Razor and jquery stuff.
http://jsfiddle.net/zrDtU/
The html
<select class="input-block-level" id="OfferType" name="OfferType" data-bind="options: offerTypes, value: selectedOfferType, optionsText: 'DisplayName'"></select>
<select class="input-block-level" id="OfferTypeDetails" name="OfferTypeDetails" data-bind="options: offerDetails, value: selectedOffer, optionsText: 'DisplayName'"></select>
The javascript
//I can't post a link to jsFiddle without code
var offerType = function (offerTypeId, displayName, offerTypeDetailsTypes) {
var self = this;
self.OfferTypeId = offerTypeId;
self.DisplayName = displayName;
self.OfferTypeDetailsTypes = offerTypeDetailsTypes;
};
var offerTypeDetailsType = function (offerTypeDetailsTypeId, displayName, offerTypeId) {
var self = this;
self.OfferTypeDetailsTypeId = offerTypeDetailsTypeId;
self.DisplayName = displayName;
self.OfferTypeId = offerTypeId;
};
function viewModel() {
var self = this;
self.selectedOfferType = ko.observable();
self.selectedOffer = ko.observable();
self.offerTypes = ko.observableArray([
new offerType('1', 'Purchase Discount'),
new offerType('2', 'Savings')
]);
self.offerTypeDetailsTypes = ko.observableArray([
new offerTypeDetailsType('1', 'Spend $10 Get $1 Off', '1'),
new offerTypeDetailsType('2', 'Spend $100 Get 10% Off', '1'),
new offerTypeDetailsType('3', '$ Half Off', '2')
]);
self.offerDetails = ko.computed({
read: function () {
var activeCategories = ko.observableArray();
ko.utils.arrayForEach(self.offerTypeDetailsTypes(), function (item) {
if (item.OfferTypeId == self.selectedOfferType().OfferTypeId) activeCategories.push(item);
});
return activeCategories();
},
deferEvaluation: true
});
}
ko.applyBindings(new viewModel());
It looks like your issue is elsewhere.

Resources