Obecnie pracuję nad aplikacją Witryny Spa i próbując użyć Knockout.js. Jest na platformie MVC z API DBDatacontroller przy użyciu Eventsot for Data i Widok JavaScript View. Mam złożony model widoku i biegam w trudnej sytuacji, głównie ze względu na bycie nowym, aby nowić. Moim największym problemem wydaje się mieć dostęp do obserwatorów. Baza danych jest zorganizowana dość:

    function AdvanceSearch(data) {
var self = this;
self.AdvanceSearchID = ko.observable(data.AdvanceSearchID);
self.FieldTypeEnum = ko.observable(data.FieldTypeEnum);
self.AnswerType = ko.observable(data.AnswerType);
self.UserValues = ko.observableArray(ko.utils.arrayMap(data.UserValues, function (item) {
    return new UserValue(item);
}));
upshot.addEntityProperties(self, "AdvanceSearch:#A.Lib.Repository");
};

function UserValue(data) {
var self = this;

self.UserProfileID = ko.observable(data.UserProfileID);
self.LoginID = ko.observable(data.LoginID);
self.AdvanceSearchID = ko.observable(data.AdvanceSearchID);
self.FieldValueCount = ko.observable(data.FieldValueCount);
self.FieldValueText = ko.observable(data.FieldValueText);
    upshot.addEntityProperties(self, "UserValue:#A.Lib.Repository");
});
};


function AnswerType(data) {
var self = this;
self.AnswerTypeID = ko.observable(data.AnswerTypeID);
self.AnswerTypeText = ko.observable(data.AnswerTypeText);
self.Answers = ko.observableArray(ko.utils.arrayMap(data.Answers, function (item) {
    return new Answer(item);
}));
self.AnswerSliders = ko.observableArray(ko.utils.arrayMap(data.AnswerSliders, function (item) {
    return new AnswerSlider(item);
}));
upshot.addEntityProperties(self, "AnswerType:#A.Lib.Repository");
}

function Answer(data) {
var self = this;
self.AnswerTypeID = ko.observable(data.AnswerTypeID);
self.AnswerEnum = ko.observable(data.AnswerEnum);
self.AnswerText = ko.observable(data.AnswerText);
upshot.addEntityProperties(self, "Answer:#A.Lib.Repository");
}

function AnswerSlider(data) {
var self = this;
self.SliderID = ko.observable(data.SliderID);
self.AnswerTypeID = ko.observable(data.AnswerTypeID);
self.SliderType = ko.observable(data.SliderType);
self.Seed = ko.observable(data.Seed);
upshot.addEntityProperties(self, "AnswerSlider:#A.Lib.Repository");
}

A mój model widoku to tylko:

function ASViewModel() {
// Private
var self = this;
var dataSourceOptions = {
    providerParameters: {
        url: "/api/Dating",
        operationName: "GetDatingProfile"
    },
    entityType: "AdvanceSearch:#A.Lib.Repository",
    bufferChanges: false,
    mapping: AdvanceSearch
};

// Public Properties
self.dataSource = new upshot.RemoteDataSource(dataSourceOptions)
                            .refresh();
self.AdvanceSearchs = self.dataSource.getEntities();
}

Więc moje znaczniki jest coś takiego

    <ol data-bind="foreach: AdvanceSearch">
   <!-- ko if: FieldTypeEnum()===5 -->
       <select data-bind="options: AnswerType().Answers, optionsText: 'AnswerText', optionsValue: 'AnswerEnum', optionsCaption: 'Not Specified', value: UserValues().FieldValueText"></select>
   <!-- /ko -->
    <!-- ko if: FieldTypeEnum()===11 -->
        <input type="text" class="multilinetext" data-bind="attr: { id: 'value_'+AdvanceSearchID()}, value: UserValues().FieldValueText" />
    <!-- /ko -->

Więc w zasadzie, bez względu na to, co robię, nie mogę uzyskać dostępu do wartości przedmiotów. Gdziekolwiek uzyskałem dostęp do jednej gałęzi, tj. AdvanceSearch().AnswerType().Answers, próbując uzyskać $parents[1].UserValues[].FieldValueText wydaje się zawsze być niezdefiniowany. Tak jak powiedziałem, jestem nowy, aby nokaut, więc prawdopodobnie coś brakuje. Czy powinienem używać wielu wizjera lub czegoś podobnego? (A jeśli tak, jak by to zrobił?) Dzięki.

1
Mike 30 wrzesień 2012, 11:36

2 odpowiedzi

Najlepsza odpowiedź

Na podstawie twoich komentarzy, myślę, że teraz wiem, co próbujesz zrobić. Idę do abstrakcji, aby łatwiej było podążać, że twój ViewModel i obiekty są bardzo złożone i nie są łatwe do zrozumienia bez wyjaśnienia.

Jeśli masz typy obiektów, Book i Author z konstruktorami:

function Book(data) {
    this.ISBN = ko.observable( data.ISBN );
    this.Title = ko.observable( data.Title );
    this.AuthorID = ko.observable( data.AuthorID );
    /* other properties */
}

function Author(data) {
    this.AuthorID = ko.observable( data.AuthorID );
    this.Name = ko.observable( data.Name );
    /* other properties */
}

Aby wybrać książkę z pola {x0}} i mieć wyświetlanie input związany z nazwą autorów, potrzebujesz Viewmodel:

var vm = {};
vm.books = ko.observableArray( /* initial data */ );
vm.authors = ko.observableArray( /* initial data */ );
vm.selectedBook = ko.observable(null);
vm.selectedBooksAuthor = ko.computed( function() {
    var authors = vm.authors(),
        selectedBook = vm.selectedBook();
    if( !selectedBook ) return null; // cannot get .AuthorID() if selectedBook == null
    var id = selectedBook.AuthorID();
    for( var a in authors ) {
        if( authors[a].AuthorID() == id )
            return authors[a];
    }
})

I twój HTML:

<select data-bind="options: books,
                   optionsText: 'Title',
                   optionsCaption: 'Select a book...',
                   value: selectedBook"></select>
<!-- ko with: selectedBooksAuthor -->
<input type="text" data-bind="value: Name" />
<!-- /ko -->

Uwaga: może to uzyskać dość nieefektywne nad dużymi zestawami danych - spójrz na używanie lepszego algorytmu wyszukiwania (zamiast "liniowy" używany tutaj) dla twojego computed observable I. selectedBooksAuthor

EDYTUJ:

Proszę zobaczyć To skrzypca dla demonstracji pracy.

0
Sethi 8 październik 2012, 09:00

Twój:

<ol data-bind="foreach: AdvanceSearch">

Musi być:

<ol data-bind="foreach: AdvanceSearchs">

Zwróć uwagę na pluralizację advansearch do advansearch

Edytuj:

Również UserValues jest obserwowalną tablicą, stąd nie można uzyskać dostępu UserValues().FieldValueText.

Należy pamiętać, że dokładnie to, co jest oczekiwane wyjście, ale wyświetla to wejście na UserValue:

<!-- ko foreach: UserValues -->
    <input type="text" class="multilinetext" data-bind="attr: { id: 'value_'+UserProfileID()}, value: FieldValueText" />
<!-- /ko -->

NB: Zmieniłem się, identyfikator wejścia do czegoś innego, aby uniknąć duplikatów IDS - to zakłada {X0}} jest wyjątkowy na {x1}}

Dalej,

Czy mogę skierować Cię do dokumentacji dla opcje nokautów. Opcje wiązania danych dla elementu {x0}} są:

options: - Jest to lista opcji do wiązania elementu select do

optionsText: Dla każdej pozycji na liście, właściwość do wyświetlania w elemencie select

optionsCaption: tekst dla pierwszego / "manekina" elementu select

value: Należy to być obserwowalne i jest związany z bieżącym wyborem elementu select

Wiązanie value jest bardzo przydatną cechą nokautu. Usuwa potrzebę martwić się IDS - a tym samym optionsValue - jak masz dostęp do całego wybranego obiektu.

Więc wiązanie select może wyglądać:

<select data-bind="options: AnswerType().Answers,
                   optionsText: 'AnswerText',
                @* optionsValue: 'AnswerEnum', *@
                   optionsCaption: 'Not Specified',
                   value: selectedAnswer"></select>

Zakładając, że dodałeś obserwowalny selectedAnswer do twojego Viewmodel.

0
Sethi 1 październik 2012, 10:23