2014-09-05 2 views
6

Può un knockout custom element avere l'attributo params associato a un oggetto come un Component binding può?Un elemento personalizzato può essere passato un oggetto per i parametri come può fare il binding del componente?

Ad esempio ho il seguente componente definita:

ko.components.register('user-widget', { 
    template: '<p><span data-bind = "text:fullName" ></span></p>', 
    viewModel: function (params) { 
     this.fullName = params.firstName + ' ' + params.lastName; 
    } 
}); 

E seguente VM:

function VM() { 
    this.user = { 
     firstName: 'Joe', 
     lastName: 'Baker' 
    }; 
} 

Quando si utilizza un componente legante posso passare la proprietà utente del VM direttamente ai params attributo in questo modo:

<div data-bind='component:{name:"user-widget", params:user}'></div> 

Tuttavia quando si utilizza un elemento personalizzato devo unboxing t ha proprietà utente in questo modo:

<user-widget params="firstName:user.firstName, lastName:user.lastName"></user-widget> 

Ho provato ad utilizzare un elemento personalizzato con il legame di un componente in questo modo:

<user-widget data-bind='component:{params:user}'></user-widget> 

che si traduce nella seguente errore:

Cannot use the "component" binding on a custom element matching a component

JsFiddle

risposta

4

Bene, è necessario modificare il componente per accettare un parametro utente anziché ogni parametro separato.

<user-widgetx params='user: user'></user-widgetx> 
ko.components.register('user-widgetx', { 
    template: '<p><span data-bind = "text:fullName" ></span></p>', 
    viewModel: function (params) { 
     this.fullName = params.user.firstName + ' ' + params.user.lastName; 
    } 
}); 

fiddle


ho esplorato l'idea di tweaking provider vincolante nell'agganciarsi codice di analisi. Sono stato in grado di far funzionare le cose. Ma devo avvertirti, questo è assolutamente un trucco. Questo è stato testato utilizzando Knockout v3.2 e non garantisco che funzionerà sempre. Almeno, finché non aggiungono altri modi per estendere le funzionalità principali di knockout.

Guardando la fonte, ho notato che il codice di analisi params utilizza il parser di binding incorporato di knockout. Quindi, se possiamo in qualche modo collegare il parser, possiamo regolare il modo in cui le stringhe di binding vengono interpretate per ottenere ciò che vogliamo.

L'obiettivo qui è creare un nuovo tipo di bind in modo che l'espressione analizzata debba essere trattata come oggetto vincolante effettivo. Questo potrebbe avere ulteriori usi al di fuori dei parametri del componente. In questo modo, siamo in grado di fare questo in nostri attacchi/params:

<user-widget params='${user}'></user-widget> 

Ora qualsiasi cosa all'interno della ${ } possono essere trattati come oggetto l'/ binding params.

(function() { 
    var originalParseBindingsString = ko.bindingProvider.prototype.parseBindingsString, 
     re = /^\$\{(.+)\}$/; 

    function extractBindableObject(objExpr, bindingContext, node, options) { 
     var objBindingString = '_object: ' + objExpr, 
      objGetter = originalParseBindingsString.call(this, objBindingString, bindingContext, node, options), 
      obj = objGetter['_object'](); 
     return objectMap(obj, function (value) { 
      return function() { return value; }; 
     }); 
    } 

    function objectMap(obj, mapper) { 
     if (!obj) return obj; 
     var result = {}; 
     for (var prop in obj) { 
      if (obj.hasOwnProperty(prop)) 
       result[prop] = mapper(obj[prop], prop, obj); 
     } 
     return result; 
    } 

    ko.bindingProvider.prototype.parseBindingsString = function (bindingsString, bindingContext, node, options) { 
     var m = bindingsString.match(re); 
     if (m) { 
      return extractBindableObject.call(this, m[1], bindingContext, node, options); 
     } 
     return originalParseBindingsString.apply(this, arguments); 
    }; 
}()); 

fiddle

+0

che non è esattamente quello che sto cercando. So di poter passare un parametro individuale come un oggetto come quello che hai mostrato. Tuttavia, voglio associare l'attributo params a un singolo oggetto come può essere fatto con il binding del componente. –

+0

Ho paura che quello che stai cercando non sia al momento possibile.Guardando all'origine, i componenti personalizzati cercheranno in particolare l'attributo 'params'. Tuttavia, utilizza il provider di binding per analizzare i binding, quindi se lo si desidera, è possibile creare un nuovo schema di associazione in modo da poter utilizzare invece l'oggetto passato come binding analizzati. –

+0

Spiacente, questo non funziona, sembra che il fornitore di binding non possa essere collegato a. in questo caso –