简体   繁体   中英

Knockout Selected Option By Text Value

I have an application that allows users to make Courses with multiple course areas. A course area is selected from a select drop down list. The list is data-binded using knockout.

HTML

<select id="courseAreaType" name="selectCourseArea" class="form-control" data-bind="options:$parent.courseAreaTypes, optionsText: 'name', optionsValue:'id', optionsAfterRender:$parent.setIconPath, value:typeid"></select>

What I need to do is when the course is loaded, load the different course areas, which I have done. For each course area it needs to load its values into its various controls.

I have been able to load the select drop down with the list of values from the DB, and allow when a user selects an option and saves the course area, it successfully saves the courseArea name.

Now what I need to do is when each course area is loaded again, it selects the option from the dropdown, based on courseArea.Name

Knockout

var CourseViewModel = function (courseIn) {
    var self = this;
    if (courseIn === undefined) {
        courseIn = {};
    }

    self.id = courseIn.Id;
    self.name = ko.observable(courseIn.Name);
    self.postalCode = ko.observable(courseIn.PostalCode);
    self.city = ko.observable(courseIn.City);
    self.province = ko.observable(courseIn.Province);
    self.courseId = ko.observable(courseIn.CourseId);
    self.courseAreas = ko.observableArray();
    self.courseAreaTypes = ko.observableArray();

    $.each(courseIn.CourseAreas, function(index, courseArea) {
        self.courseAreas.push(new CourseAreaViewModel(courseArea));
    });

    $.getJSON("/Course/GetCourseAreaTypes", function (types) {
        $.each(types, function (index, type) {
            self.courseAreaTypes.push(new CourseAreaTypeViewModel(type));
        });
    });

    $.each(courseIn.CourseAreas, function (index, courseArea) {
        console.log(courseArea.Name);
        var list = $('#courseAreaType');
        var options = $('option', list); // This is where my problem is
    });

    self.setIconPath = function (option, courseAreaType) {
        $(option).data("icon",  courseAreaType.iconPath)
        //console.log($(option).data("icon"));
    }
}

var CourseAreaTypeViewModel = function (courseAreaTypeIn) {
    var self = this;

    if (courseAreaTypeIn === undefined) {
        courseAreaTypeIn = {};
    }

    self.id = courseAreaTypeIn.ID;
    self.name = courseAreaTypeIn.Name;
    self.iconPath = courseAreaTypeIn.iconPath;
}

var CourseAreaViewModel = function(courseAreaIn) {
    var self = this;
    if (courseAreaIn === undefined) {
        courseAreaIn = {};
    }
    self.id = courseAreaIn.Id;
    self.name = ko.observable(courseAreaIn.Name);
    self.acreage = ko.observable(courseAreaIn.Acreage);
    self.goals = ko.observable(courseAreaIn.Goals);
    self.typeid = ko.observable(courseAreaIn.TypeID);
    self.selectedOption = ko.observable();
}

I've tried changing it based on getting the element id, I've tried .val, .prop, .attr without any success. When I log the data to the console of the element, it's not showing the values in the dropdown, so I have a feeling knockout is adding the values on a script level, and jquery is unable to see those values.

The basic approach to this is that you need to bind the value of the select element to an observable that holds the ID of the course type that should be selected.

I've doe a simple fiddle that shows this in action:

http://jsfiddle.net/9a1njj1g/2/

The JS is:

function CourseArea(types) {
   this.types = ko.observableArray(types);
   this.typeid = ko.observable(2); 
};


var types = [
    { id: 1, name: "one" },
    { id: 2, name: "two" },
    { id: 3, name: "three" }
];

ko.applyBindings(new CourseArea(types));

The HTML is:

<select data-bind="options: types, optionsText: 'name', optionsValue: 'id', value: typeid"></select>

To apply this to your code, I don't think you have much to do. Maybe refactor your JS slightly, so you only process your CourseAreas once you've loaded all your CourseAreaTypes:

$.getJSON("/Course/GetCourseAreaTypes", function (types) {
    // Load all the types first.
    $.each(types, function (index, type) {
        self.courseAreaTypes.push(new CourseAreaTypeViewModel(type));
    });

    // Continue here, to be sure you have a complete list of types to work with.
   $.each(courseIn.CourseAreas, function (index, courseArea) {
        self.courseAreas.push(new CourseAreaViewModel(courseArea));
    });
});

Also ensure the ID you're selecting in CourseAreaViewModel.typeid has an equivalent exact value in a CourseAreaTypeViewModel.id.

And ensure your data matches up to the code OK... eg the types data must supply its ID in capitals for self.id = courseAreaTypeIn.ID to be useful. If not then you won;t get an error, because self.id will be quietly set to undefined .

Here's a fiddle showing all this working with Courses, Areas and Types:

http://jsfiddle.net/vpe4ut3m/1/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM