Hiding radio options depending on other seperate radio option in knockout [closed] - json

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I plan to have two sets of radio options on my form, one radio called Operating System and another radio called Database.
The option selected by the Operating System radio dictates the values available for selection in the Database radio group.
In my json object the requires field indicates the visibility of the option when the sku of the Operating System is selected. If no requires field is provided for a database option, then it will always be available regardless of the selected operating system.
How would one approach this in knockout, or do I need to rethink my approach?
My jsfiddle is here
var osOptions = [{
name: "Windows Standard",
sku: "201",
},{
name: "Windows Enterprise",
sku: "202",
}, {
name: "CentOS Linux",
sku: "203",
}, {
name: "Debian",
sku: "204",
}];
var databaseOptions = [{
name: None,
}, {
name: "SQL Express",
sku: 401,
requires: ["201", "202"]
}, {
name: "SQL Standard",
sku: 402,
requires: ["202"]
}, {
name: "MySQL",
sku: "MySQL1",
requires: ["201", "202", "203"]
}, {
name: "RavenDb",
sku: 403,
}, {
name: "MongoDB",
sku: 404,
requires: ["204"]
}];
function viewModel() {
this.os = osOptions;
this.database = databaseOptions;
this.selectedOs = ko.observable();
this.selectedDb = ko.observable();
}
ko.applyBindings(new viewModel);
<!- view html -->
<h1>Select OS:</h1>
<div data-bind="foreach: os" >
<div>
<input type="radio" name="optionsGroup" data-bind="attr: {value: name}, checked: $root.selectedOs" />
<span data-bind="text: name"></span>
</div>
</div>
<h1>Select Db</h1>
<div data-bind="foreach: database" >
<div>
<input type="radio" name="optionsGroup" data-bind="attr: {value: name}, checked: $root.selectedDb" />
<span data-bind="text: name"></span>
</div>
</div>

I would create a different computed collection availableDatabases where
first I would look up the currently selected OS
then I would use the ko.utils.arrayFilter to filter out the databases where the the requires array does not contain the selected sku.
So I would write something like this:
this.availableDatabases = ko.computed(function() {
var selectedOsName = this.selectedOs();
var selectedOs = ko.utils.arrayFirst(this.os, function(os){
return os.name == selectedOsName;
}, this);
if (!selectedOs)
return [];
return ko.utils.arrayFilter(this.database, function(db){
return db.requires && db.requires.indexOf(selectedOs.sku) > -1;
}, this)
}, this);
And use this new collection in the view:
<div data-bind="foreach: availableDatabases" >
<div>
<input type="radio" name="optionsGroup"
data-bind="attr: {value: name}, checked: $root.selectedDb" />
<span data-bind="text: name"></span>
</div>
</div>
Demo JSFiddle.
Note If you have the sku instead of the name as the value for you first radio buttons:
<input type="radio" name="optionsGroup"
data-bind="attr: {value: sku}, checked: $root.selectedOs" />
Then there is no lookup needed in the computed because selectedOs would contain the sku property directly (Demo)...

Take a look at this fiddle
You can create an computed that retrieves the available databases.
JS :
function viewModel() {
var self = this;
this.os = osOptions;
this.database = databaseOptions;
this.selectedOs = ko.observable();
this.selectedDb = ko.observable();
this.availableDatabase = ko.computed(function () {
var osSku = self.selectedOs();
return ko.utils.arrayFilter(self.database, function (dbItem) {
if (osSku == null) return false;
if (dbItem.requires == null) return true;
var dbs = ko.utils.arrayFirst(dbItem.requires, function (requiredOS) {
return requiredOS == osSku;
}) != null;
return dbs;
});
});
};
ko.applyBindings(new viewModel);
I hope it helps.

Related

Radio button issues with multiple-choice quiz

I'm making a website where you can make quizzes and answer them. My issue is that when I try to answer my quiz, to see whether the answer is correct or incorrect, the result I get is not exactly what I want.
I'm creating my html page by loading a json and assigning a radio button to every answer. The structure is that a quiz can have many questions, and questions can have many answers.
HTML:
<table class="pageTable" align="center">
<!-- Quiz title -->
<div *ngFor="let quiz of quizToDisplay"><br/>
Quiz title: {{quiz.title}} <br/> by {{quiz.owner}}<br/><br/>
<!-- Quiz questions -->
<div *ngFor="let quizQuestions of quiz.questions" align="center">
<div class="Question-panel-title" style="padding: 10px; word-wrap: break-word;">
Question: {{quizQuestions.questionText}}
</div>
<!-- Quiz answers -->
<div class="Question-panel-content" style="padding: 5px; word-wrap: break-word;">
<div *ngIf="quizQuestions.types == 'Multiple-choice'" >
<div *ngFor="let quizAnswers of quizQuestions.answers; let i=index">
<input type="radio" id="rawr" name="{{quizQuestions.questionText}}" value="{{quizAnswers.correctAnswer}}" [disabled]="submitted">
{{i + 1}}: {{quizAnswers.answerText}}
</div>
<div *ngIf="submitted == true">
Your answer is {{correctAnswerMultipleChoice}}
</div>
</div>
<div *ngIf="quizQuestions.types == 'Checkboxes'">
<div *ngFor="let quizAnswers of quizQuestions.answers; let i=index">
<input type="checkbox" name="checkboxGroup" value="{{quizAnswers.correctAnswer}}" [disabled]="submitted" (click)="handleCheckboxAnswer(i, quizAnswers.correctAnswer)">
{{i + 1}}: {{quizAnswers.answerText}}
</div>
<div *ngIf="submitted == true">
Your answer is {{correctAnswerCheckbox}}
</div>
</div>
</div><br/>
</div>
<input type="submit" value="Submit" (click)="submitAnswer()">
<input type="submit" value="View Statistics">
<div *ngIf="quiz.owner == currentUser">
<input type="submit" value="Delete Quiz" (click)="deleteQuiz(quiz.id)">
</div>
</div>
Code:
export class QuizComponent implements OnInit, OnDestroy {
service: any;
data: any;
quizToDisplay: any;
currentUser: string;
correctAnswerMultipleChoice: string = 'Incorrect';
CheckboxesValues: string[] = [];
correctAnswerCheckbox: string = 'Incorrect';
submitted: boolean = false;
answersArray: any[] = [];
constructor(private router:Router, private quizObserverService:QuizObserverService, private socketService:SocketService, private elementRef:ElementRef){
this.currentUser = localStorage.getItem('user');
}
ngOnInit() {
this.service = this.quizObserverService.getQuiz(this.router.url).subscribe(data => { //only gets JSON upon page load
this.quizToDisplay = data;
})
}
ngOnDestroy() {
this.service.unsubscribe();
}
deleteQuiz(id: string){
this.socketService.socket.emit('deleteQuiz', JSON.stringify(id));
this.router.navigateByUrl('/home');
}
handleMultiplechoiceAnswer(){
let rawr = this.elementRef.nativeElement.querySelectorAll('#rawr');
for(let i = 0; i < this.quizToDisplay[0].questions.length; i++){
if(this.quizToDisplay[0].questions[i].types == "Multiple-choice"){
for(let j = 0; j < this.quizToDisplay[0].questions[i].answers.length; j++){
this.answersArray.push(this.quizToDisplay[0].questions[i].answers[j]);
}
}
}
if(this.handleMultiplechoiceAnswerCorrect(rawr)){
return this.handleMultiplechoiceAnswerCorrect(rawr);
}
else
{
return this.handleMultiplechoiceAnswerIncorrect(rawr);
}
}
handleMultiplechoiceAnswerCorrect(rawr: any){
for(let k = 0; k < rawr.length; k++){
if(this.answersArray[k].correctAnswer == rawr[k].value && rawr[k].value == "Correct" && rawr[k].checked == true){
return "Correct";
}
}
}
handleMultiplechoiceAnswerIncorrect(rawr: any){
return "Incorrect";
}
handleCheckboxAnswer(index: number, correct: string) {
this.CheckboxesValues[index] = correct;
}
submitAnswer(){
this.submitted = true;
this.correctAnswerMultipleChoice = this.handleMultiplechoiceAnswer();
}
When I try to answer my quiz, this is what the result looks like:
Image
As you can see, even though the second question is answered wrong, it still says that it is correct, because the first question is answered correctly. The method I'm using to determine whether the quiz is correct or false is the handleMultiplechoiceAnswer() method, so I think something is wrong in that method, however I can't pick my finger on it. Thanks for the help.
EDIT:
Very sorry, I forgot to put an example of my json structure. Here it is:
{
"id": "32bec4d6-b5fd-4360-bede-9c902abd95de",
"title": "random quiz",
"owner": "mohemohe",
"questions": [
{
"questionText": "Choose numbers above 10",
"answers": [
{
"answerText": "9",
"correctAnswer": "Incorrect"
},
{
"answerText": "11",
"correctAnswer": "Correct"
}
],
"types": "Multiple-choice"
},
{
"questionText": "Which website is this?",
"answers": [
{
"answerText": "stackoverflow",
"correctAnswer": "Correct"
},
{
"answerText": "google",
"correctAnswer": "Incorrect"
}
],
"types": "Multiple-choice"
}
],
"access": "Public"
}
EDIT 2:
Managed to make a plunker example: https://plnkr.co/edit/CoV1AQtVtbbS2kNYK7FR
The solve:
I think that the reason why this is always returning true / 'Correct' is because of the if statement evaluating it:
if(this.answersArray[k].correctAnswer == rawr[k].value && rawr[k].value == "Correct" && rawr[k].checked == true){...}
If we break this down...
this.answersArray[k].correctAnswer == rawr[k].value
rawr[k].value == "Correct"
rawr[k].checked == true
Instantly you can see that you are expecting rawr[k].value to equal both correctAnswer AND 'Correct'. Because the result is always returning true, this means that this.answersArray[k].correctAnswer == 'Correct'.
So this essentially negates the first 2 conditions in your if statement - so essentially your if statement becomes... if(rawr[k].checked == true).
Just FYI there is absolutely no need for even checking rawr[k].checked == true if you swap querySelectorAll('#rawr'); to querySelectorAll('#rawr:checked');
The following is just general feedback:
I think that you really need to consider re-working this entire script. It is very hard to read, highly un-optomised and needs to be refactored into a more robust approach.
First I would recommend creating a variable to store the currentQuestion so that you don't have to do quizToDisplay[0] every single time.
var currentQuestion: any;
ngOnInit(){
....
this.quizToDisplay = data;
this.currentQuestion = this.quizToDisplay[0];
}
Or at the very least... this.quizToDisplay = data[0]
Go and check out es6 array methods.
for(let i = 0; i < this.quizToDisplay[0].questions.length; i++){
if(this.quizToDisplay[0].questions[i].types == "Multiple-choice"){
for(let j = 0; j < this.quizToDisplay[0].questions[i].answers.length; j++){
this.answersArray.push(this.quizToDisplay[0].questions[i].answers[j]);
}
}
}
Can be transmutted into the following which is much easier to read:
this.quizToDisplay[0].questions.forEach((questionGroup, i)=>{
if(questionGroup.types == "Multiple-choice"){
questionGroup.forEach((question, ii)=>{
this.answersArray.push(question.answers[ii]);
});
}
});
Why not just include the feedback string in the json for each question? That way you can do something like the following and mitigate any future requirements that the feedback string is unique for a particular question:
<div *ngIf="submitted == true">
<p *ngIf="correct" class="correct-colour">{{quizAnswers.correctFeedback}}</p>
<p *ngIf="!correct" class="incorrect-colour">{{quizAnswers.incorrectFeedback}}</p>
</div>
I think that the naming conventions need to be improved. for example: quizQuestions.answers should be quizQuestions.options.
Don't forget that as you are using an object, you have the ability to assign new object properties "on the fly". For example you could do:
this.quizToDisplay[0]['answeredCorrectly'] = true;
I would strongly recommend creating a click event on your <input> so that you can trap the selected options more effectively. Using the above methodology you could...
// .html
<input ... (click)="optionClicked(option)">
// .ts
optionClicked(_option: Object){
quizQuestions['clicked'] = !quizQuestions['clicked'] || true;
}
If you ever want future code review, try codereview.stackexchange.com
{
"id": "32bec4d6-b5fd-4360-bede-9c902abd95de",
"title": "random quiz",
"owner": "mohemohe",
"questions": [
{
"questionText": "Choose numbers above 10",
"answers": [
{
"answerText": "9",
"correctAnswer": "Incorrect"
},
{
"answerText": "11",
"correctAnswer": "Correct"
}
],
"types": "Multiple-choice"
},
{
"questionText": "Which website is this?",
"answers": [
{
"answerText": "stackoverflow",
"correctAnswer": "Correct"
},
{
"answerText": "google",
"correctAnswer": "Incorrect"
}
],
"types": "Multiple-choice"
}
],
"access": "Public"
}

Select tag not working properly with Anuglar

I'm building a form using Angular.
in my form, there is a type of select as a tag.
Below is my code:
<div class="form-group" ng-class="{ 'has-error': form.$submitted && form['{{field.id}}'].$invalid }" ng-if="field.type === 'select'">
<select>
<div class="" ng-repeat="value in field.values">
<option value="">{{value.title}}</option>
</div>
</select>
</div>
And here is json file for field.values:
"values": [
{
"id": 0,
"title": "Not Selected"
},
{
"id": 1,
"title": "Yes"
},
{
"id": 2,
"title": "No"
}
]
Javascript(changes made):
app.controller('I129Ctrl', ['$scope', '$http', 'JSONModelsService',
function ($scope, $http, JSONModelsService) {
var formData = {};
$scope.groups = [];
$scope.sections = [];
$scope.fields = [];
//below is basically equivalent to routing
JSONModelsService.get(['test', 'Valid Passport'])
.then(function (response) {
console.log(response);
// $scope.group = response.data.groups[0];
$scope.groups = response.data.groups;
$scope.sections = $scope.groups.sections;
$scope.fields = $scope.groups.sections.fields;
});
Basically, I first check whether field.type is equal to select. If so, I want to values in select type of question. However, it is not working as I imagine. What am I doing wrong?
First don't use a div element in a select this can't work. You can put ng-repeat in option level but this won't work since you don't have ng-model binded with this.
The way of doing it is the directive ng-options in select tag.
<select ng-model="valueSelected" ng-options="value as value.title for value in field.values"></select>
If you want to let your user being able to not select/unselect a value. Add in the select the following option :
<option ng-value="null">-- No value--</option>

How to add a tooltip based on a DropDown list

Basically I have a Kendo Grid where a couple of my columns also have Kendo DropDowns.
I would like to attach a ToolTip based on the value the user chooses from the "Instrument" dropdown.
Here's my grid javascript code (using MVVM pattern):
tradesGrid = $("#tradesGrid").kendoGrid({
dataSource: datasource,
toolbar: [
{ name: "create", text: "Add Trade" }
],
columns: [{
field: "TradeId"
},
{
field: "Instrument",
editor: instrumentsDropDownEditor, template: "#=Instrument#"
},
{ command: ["edit", "destroy"] },
],
sortable: true,
editable: "popup",
});
and here's the Editor function for the Instrument dropdown :
function instrumentsDropDownEditor(container, options) {
var instrItems = [{
"optionInstr": "OPTION 22/11/2013 C70 Equity"
}, {
"optionInstr": "OPTION 26/11/2013 C55 Equity"
},
{
"optionInstr": "OPTION 30/11/2013 C80 Equity"
}
];
var input = $('<input id="Instrument" name="Instrument">');
input.appendTo(container);
input.kendoDropDownList({
dataTextField: "optionInstr",
dataValueField: "optionInstr",
dataSource: instrItems, // bind it to the brands array
optionLabel: "Choose an instrument"
}).appendTo(container);
}
and on my Html view file I'm starting with this idea :
<span class="key-button"
title="Instrument Details!!!"
data-role="tooltip"
data-auto-hide="true"
data-position="right"
data-bind="events: { show: onShow, hide: onHide }"
</span>
I don't have time to rig up a jsFiddle right now, but I'm pretty sure this would work...
Init your tooltip in javascript, and specify content that is a function:
var myTooltip = "";
var tooltipWidget = $("#whatever").kendoTooltip({
filter: "a",
content: function (item) { return myTooltip; },
...
}).data("kendoTooltip");
Then on your dropdown widget, specify a change function handler that sets myTooltip to whatever contents you want.
var onSelect = function (e) {
myTooltip = ...;
tooltipWidget.refresh();
};
$("#dropdownlist").kendoDropDownList({
select: onSelect,
...
});
Or you can change the title property on your HTML element, if that is easier. However, the tooltip widget won't refresh its contents after it has been displayed, which is why you need to manually call tooltipWidget.refresh() after you change the contents.

I cannot get my jqGrid to populate

Edited with working code as per Mark's answer below.
I'm really starting to loath MVC. I have been trying all day to get a simple grid to work, but I'm having more luck banging a hole in my desk with my head.
I'm trying to implement a search page that displays the results in a grid. There are 3 drop-down lists that the user can use to select search criteria. They must select at least one.
After they have searched, the user will be able to select which records they want to export. So I will need to include checkboxes in the resulting grid. That's a future headache.
Using JqGrid and Search form - ASP.NET MVC as a reference I have been able to get the grid to appear on the page (a major achievement). But I can't get the data to populate.
BTW, jqGrid 4.4.4 - jQuery Grid
here is my view:
#model Models.ExportDatex
<script type="text/javascript">
$(document).ready(function () {
$('#btnSearch').click(function (e) {
var selectedSchool = $('#ddlSchool').children('option').filter(':selected').text();
var selectedStudent = $('#ddlStudent').children('option').filter(':selected').text();
var selectedYear = $('#ddlYear').children('option').filter(':selected').text();
var selectedOption = $('#exportOption_1').is(':checked');
if (selectedSchool == '' && selectedStudent == '' && selectedYear == '') {
alert('Please specify your export criteria.');
return false;
}
selectedSchool = (selectedSchool == '') ? ' ' : selectedSchool;
selectedStudent = (selectedStudent == '') ? ' ' : selectedStudent;
selectedYear = (selectedYear == '') ? ' ' : selectedYear;
var extraQueryParameters = {
school: selectedSchool,
student: selectedStudent,
year: selectedYear,
option: selectedOption
};
$('#searchResults').jqGrid({
datatype: 'json',
viewrecords: true,
url: '#Url.Action("GridData")?' + $.param(extraQueryParameters),
pager: '#searchResultPager',
colNames: ['SchoolID', 'Student Name', 'Student ID', 'Apprenticeship', 'Result'],
colModel: [
{ name: 'SchoolID' },
{ name: 'Student Name' },
{ name: 'StudentID' },
{ name: 'Apprenticeship' },
{ name: 'Result' }]
}).trigger('reloadGrid', [{ page: 1 }]);
});
});
</script>
#using (Html.BeginForm("Index", "Datex", FormMethod.Post))
{
<h2>Export to Datex</h2>
<div class="exportOption">
<span>
#Html.RadioButtonFor(model => model.ExportOption, "true", new { id = "exportOption_1" })
<label for="exportOption_1">VET Results</label>
</span>
<span>
#Html.RadioButtonFor(model => model.ExportOption, "false", new { id = "exportOption_0" })
<label for="exportOption_0">VET Qualifications</label>
</span>
</div>
<div class="exportSelectionCriteria">
<p>Please specify the criteria you want to export data for:</p>
<table>
<tr>
<td>School:</td>
<td>#Html.DropDownListFor(model => model.SchoolID, Model.Schools, new { id = "ddlSchool" })</td>
</tr>
<tr>
<td>Student: </td>
<td>#Html.DropDownListFor(model => model.StudentID, Model.Students, new { id = "ddlStudent" })</td>
</tr>
<tr>
<td>Year Completed:
</td>
<td>
#Html.DropDownListFor(model => model.YearCompleted, Model.Years, new { id = "ddlYear" })
</td>
</tr>
</table>
<table id="searchResults"></table>
<div id="searchResultPager"></div>
</div>
<div class="exportSearch">
<input type="button" value="Search" id="btnSearch" />
<input type="submit" value="Export" id="btnExport" />
</div>
}
Here is my Controller. As we don't have a database yet, I am just hardcoding some results while using an existing table from a different DB to provide record IDs.
[HttpGet]
public JsonResult GridData(string sidx, string sord, int? page, int? rows, string school, string student, string year, string option)
{
using (SMIDbContainer db = new SMIDbContainer())
{
var ds = (from sch in db.SCHOOLs
where sch.Active.HasValue
&& !sch.Active.Value
&& sch.LEVEL_9_ORGANISATION_ID > 0
select sch).ToList();
var jsonData = new
{
total = 1,
page = 1,
records = ds.Count.ToString(),
rows = (
from tempItem in ds
select new
{
cell = new string[]{
tempItem.LEVEL_9_ORGANISATION_ID.ToString(),
tempItem.SCHOOL_PRINCIPAL,
"40161",
"No",
"Passed (20)"
}
}).ToArray()
};
return Json(jsonData, JsonRequestBehavior.AllowGet);
}
}
Is the JSON you are passing back to the grid valid? Are you passing back the information that the jqGrid needs? Why setup your jqGrid inside of an ajax call instead of inside your $(document).ready(function () { ?
Here is an example of the portion of code I use to format my json for jqGrid:
var jsonData = new
{
total = (totalRecords + rows - 1) / rows,
page = page,
records = totalRecords,
rows = (
from tempItem in pagedQuery
select new
{
cell = new string[] {
tempItem.value1,
tempItem.value2, ........
}
}).ToArray()
};
return Json(jsonData, JsonRequestBehavior.AllowGet);
If you want to make your user search first, you can on the client side, set the jqgrid datatype: local and leave out the url. Then after your user does whatever you want them to do you can have the jqGrid go out and fetch the data, via something like:
$('#gridName').jqGrid('setGridParam', { datatype: 'json', url: '/Controller/getGridDataAction' }).trigger('reloadGrid', [{ page: 1}]);
If you want to pass in the search data, or other values to the controller/action that is providing the data to the jqGrid you can pass it via the postData: option in the jqGrid. To set that before going out you can set it via the setGridParam option as shown above via postData: { keyName: pairData}.
MVC and jqGrid work great...there are a ton of examples on stackoverflow and Oleg's answers are a vast resource on exactly what you are trying to do. No hole in desk via head banging required!

Knockout dropdown form binding

I have a html form for adding multiple addresses:
http://i48.tinypic.com/jg2ruo.png
This way If I change the Address Type selection the entire form has to bind to the correct json address object:
var jsonAddresses = { Addresses:
[
{ AddressType: 1, Address1: "", Address2: "",Province:"",City:"",State:"",PostalCode:"",Municipal:"" },
{ AddressType: 2, Address1: "", Address2: "",Province:"",City:"",State:"",PostalCode:"",Municipal:"" },
{ AddressType: 3, Address1: "", Address2: "",Province:"",City:"",State:"",PostalCode:"",Municipal:"" },
{ AddressType: 4, Address1: "", Address2: "",Province:"",City:"",State:"",PostalCode:"",Municipal:"" }
]
};
I have done this with Jquery with a lot of code actually but I want to know how can I do this with Knockout. The idea is instead of having a fixed json object with the 4 types of addresses i want to have only 1 json object and if I select an address type that is not in the array then the object is added and binded, if the address type already exists in the array then just bind it. then i can have a "remove" link that when clicked the selected address type object is removed from the array.
Thanks in advance.
I'm guessing a little bit on this, because its not entirely clear. You want a single form for editing addresses, with a dropdown that lets you select which address you are editing. I've put a working fiddle together, but here are the important parts.
You have a concept of an Address object, which is observable since you will be updating the values. Then you need a viewmodel to keep track of all the address, have some concepted of the selected address, and the ability to add new addresses. This is the part that wasn't clear, so I just went with a New Address button. Let me know if you have something else in mind. Other than the list of states, and the initial address data (both which should come from the server) this is all the code, and as you can see knockout makes it pretty simple.
HTML:
<select data-bind="options: addresses, optionsText: 'typeName', value: selectedAddress"></select>
<div data-bind="with: selectedAddress">
Name: <input data-bind="value: typeName" /></br>
Line1: <input data-bind="value: address1" /></br>
Line2: <input data-bind="value: address2" /></br>
City: <input data-bind="value: city" /></br>
State: <select data-bind="options: $parent.states, value: state"></select></br>
Postal Code: <input data-bind="value: postalCode" />
</div>
<button data-bind="click: addAddress">New Address</button>
<button data-bind="click: deleteAddress">Remove Address</button>
​
ViewModels:
var Address = function(address) {
this.id = ko.observable(address.AddressType || 0);
this.typeName = ko.observable(address.TypeName || '');
this.address1 = ko.observable(address.Address1 || '');
this.address2 = ko.observable(address.Address2 || '');
this.city = ko.observable(address.City || '');
this.state = ko.observable(address.State || '');
this.postalCode = ko.observable(address.PostalCode || '');
};
var App = function(addressList) {
var self = this;
self.states = states;
self.addresses = ko.observableArray(ko.utils.arrayMap(addressList,
function(i) { return new Address(i); }
));
self.selectedAddress = ko.observable(self.addresses[0]);
self.addAddress = function() {
var newId = self.addresses()[self.addresses().length -1].id + 1;
var newAddress = new Address({AddressType: newId});
self.addresses.push(newAddress);
self.selectedAddress(newAddress);
};
self.deleteAddress = function() {
self.addresses.remove(self.selectedAddress());
self.selectedAddress(self.addresses[0]);
};
};
EDIT1: added remove button. This is for the demo, obviously you will want some safety logic when the array is empty.