2011-12-29 9 views
33

Pracuję nad przykładem wtyczki mapowania w witrynie Knockoutjs.Dodawanie właściwości do modelu widoku utworzonego za pomocą wtyczki mapowania JS Knockout

To są dane przykładowe.

Knockout JS Mapping Plugin

var data = { 
    name: 'Scott', 
    children: [ 
     { id : 1, name : 'Alice' } 
    ] 
} 

Przykład pokazuje, jak zastąpić mapowanie dla jednego z dzieci, ale w jaki sposób mogę zmienić mapowanie dla obiektu bazowego.

Jeśli na przykład chciałem dodać do Scott'a właściwość "FavouriteChild", jak bym to zrobił?

Zakładam, że muszę użyć funkcji tworzenia na mapowaniu bazy, ale nie mogę znaleźć przykładu składni w dowolnym miejscu.

var myChildModel = function(data) { 
    ko.mapping.fromJS(data, {}, this); 

    this.nameLength = ko.computed(function() { 
     return this.name().length; 
    }, this); 
} 

var mapping = { 
    'children': { 
     create: function(options) { 
      return new myChildModel(options.data); 
     } 
    } 
} 

var viewModel = ko.mapping.fromJS(data, mapping); 

EDIT: z przyjętych odpowiedź poniżej znalazłem to zadziałało

<span data-bind='text: AdditionalProperty'> 

Kod nokaut

var mapping = { 
    create: function (options) { 
     //customize at the root level. 
     var innerModel = ko.mapping.fromJS(options.data); 

     innerModel.AdditionalProperty = 'Hello World'; 

     return innerModel; 
    } 
} 

var viewModel = ko.mapping.fromJS(data, mapping); 

//use this as our model bindings 
ko.applyBindings(viewModel); 

Odpowiedz

23

Musisz użyć metody create temat samego obiektu mapowania podobne:

var mapping = { 
    //customize at the root level. 
    create: function(options) { 
    //first map the vm like normal 
    var vm = ko.mapping.fromJS(options.data); 

    //now manipulate the returned vm in any way that you like 
    vm.someProperty = "test"; 

    vm.someComputed = ko.computed(function() { 
      return vm.first() + " " + vm.last(); 
    }); 

    //return our vm that has been mapped and tweaked 
    return vm; 
    } 
}; 
+6

Jak o wyjaśnienia w jaki sposób, że tworzą z pustym funkcji pokazuje nic o dostępie do korzeni poziom i dodawanie do niego. –

+0

zaktualizowała funkcję, aby pokazać, jak można odwzorować i zmanipulować wynik przed zwróceniem go. –

+0

Wiem, że jest to bardzo stare pytanie, ale właśnie je spotkałem. Chciałem złożyć sugestię. Przykład kodu do użycia wywołania zwrotnego create podczas mapowania (w witrynie KnockoutJs) nie wyjaśnia, że ​​metoda create znajduje się w obiekcie odwzorowania. Ryan, jeśli możesz, poprosiłbym właściciela witryny, aby zastąpił próbkę kodu twoją próbką powyżej. –

13

Tutaj jest kontynuacją tej odpowiedzi w oparciu o rozwiązania RP Niemeyera

Ta odpowiedź tutaj jest oparty na rozwiązaniu powyżej ze swoim blogu - Dzięki za to! Pomyślałem, że powinienem dodać trochę szczegółów, ponieważ adresuje się, gdy tablica nie jest obiektem pierwszego poziomu.

var data = { 
person: { 
     children: [{ id: 1, firstName: 'Scot', lastName: 'Weise'}] 
    } 
}; 

var mapping = { 
    'children': { 
     create: function(options) { 
      return (new (function() { 
       // setup the computed binding for some reason I had 
       // to use ko.dependentObservable instead of ko.computed 
       // or errors showed up. 
       this.fullName = ko.dependentObservable(function() { 
        return this.firstName() + ' ' + this.lastName(); 
        }, this); 
        ko.mapping.fromJS(options.data, { }, this); 
       })(/* call the ctor here */)); 
      } 
     } 
    }; 

    // Create view model and map the data object to the model. 
    var viewModel = ko.mapping.fromJS(data, {}); 

    // update the viewModel with the mapping object that contains 
    // some a computed property(s) 
    viewModel.person = ko.mapping.fromJS(viewModel.person, mapping); 
    ko.applyBindings(viewModel); 

Należy zauważyć, że dana osoba jest obiektem pierwszego poziomu, a dzieci są podrzędną własnością tej osoby. Linia viewModel.person = ko.mapping.fromJS (viewModel.person, mapowanie) początkowo nie była dla mnie intrygująca.

I tu jest niewielka zmienność

Osoba przedmiot jest obserwowalne, która jest dodawana lub aktualizowane po to jest stworzony na podstawie danych serwera JSON.

var viewModel = {}; 
$(document).ready(function() { 
    var person = getPerson(); 

    // selected person is added to the viewModel 
    viewModel.selectedPerson = ko.observable(person); 
    ko.applyBindings(viewModel); 
}); 

function getPerson() { 
// you would probably pass this into the function as a parameter. 
var person = 
    { 
     name: 'jim', 
     children: [{ id: 1, firstName: 'jane', lastName: 'bob'}] 
    }; 

    var mapping = { 
     'children': { 
      create: function (options) { 
       return (new (function() { 
        // setup the computed binding 
        this.fullName = ko.dependentObservable(function() { 
        return this.firstName() + ' ' + this.lastName(); 
        }, this); 
        ko.mapping.fromJS(options.data, {}, this); 
       })(/* call the ctor here */)); 
      } 
     } 
    }; 

    var result = ko.mapping.fromJS(person, mapping); 
    return result; 
} 

Niektóre kod wiąże w html

Ostatecznie trzeba umieścić go w jakimś użytku w pewnym momencie tak:

<div data-bind="foreach:viewModel.selectedPerson().children"> 
    <span data-bind="text:fullName"></span> 
</div> 

dziękuję za pomoc! Nie mogłem dotrzeć tak daleko bez twojego posta na blogu.

3

pamiętać, że aby zdefiniować dodatkowe obserwable obliczone na dziecko trzeba będzie przechodzić inny zestaw opcji mapowania

var mapping = { 
    create: function(options) { 
    //customize at the root level. 

    var mapping2 = { 
     'children': { 
     create: function(options) { 
      //customize children also 

     } 
     } 
    } 

    //call ko.mapping.fromJS on the options.data as well with further customization 
    ko.mapping.fromJS(options.data, mapping2, this); 
    } 
}; 
+1

Poszukałem tutaj, jak mapować zagnieżdżone właściwości i IMHO, co było najbardziej wyraźnym przykładem. Gdyby zawierała próbkę viewModelu, byłoby to dla mnie kompletne rozwiązanie. –

0

kolejny przykład na podstawie przykładów podanych przez Jazona i RP Niemeyer.

data jest to, co otrzymujemy po zapytaniu ajax, na której dodamy dwie zagnieżdżone obserwable (viewModel.weekly.selectedWeek i viewModel.monthly.selectedMonth):

var data = { 
     "date": "2017-03-28", 
     "weekly": { 
      "weeks": [ 
       { 
        "id": "201701", 
        "label": "Week 1" 
       }, 
       { 
        "id": "201702", 
        "label": "Week 2" 
       } 
      ] 
     }, 
     "monthly": { 
      "months": [ 
       { 
        "id": "201701", 
        "label": "01/2017" 
       }, 
       { 
        "id": "201702", 
        "label": "02/2017" 
       } 
      ] 
     } 
    } 

    var viewModelMapping = { 
     create: function (options) { 
      return (new (function() { 
       // viewModel root level 
       var mapping2 = { 
        'weekly': { 
         create: function (options) { 
          // viewModel.weekly 
          return new function() { 
           var model = ko.mapping.fromJS(options.data, {}, this); 
           model.selectedWeek = ko.observable(); 
           return model; 
          }; 
         } 
        }, 
        'monthly': { 
         create: function (options) { 
          // viewModel.monthly 
          return new function() { 
           var model = ko.mapping.fromJS(options.data, {}, this); 
           model.selectedMonth = ko.observable(); 
           return model; 
          }; 
         } 
        } 
       }; 

       ko.mapping.fromJS(options.data, mapping2, this); 
      })()); 
     } 
    }; 


    var viewModel = ko.mapping.fromJS(data, viewModelMapping); 
    ko.applyBindings(viewModel); 
Powiązane problemy