Can a user element pass an object for parameters like component binding?

Can a user element's params attribute be bound to an object, how can Component Binding ?

For example, I have the following component:

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

And the following virtual machine:

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

When using component binding, I can pass the custom property of the virtual machine directly to the params attribute, for example:

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

However, when using a custom item, I have to unzip the custom property as follows:

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

I tried using a custom element bound to a component, for example:

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

This results in the following error:

Cannot use "component" binding for custom item matching Component

Jsfiddle

+6
source share
1 answer

Well, you need to modify your component to accept a custom parameter, not every single parameter.

 <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


I explored the idea of ​​setting up a binding provider to connect to the syntax code. I managed to find a job. But I must warn you, this is definitely a hack. This has been tested using Knockout v3.2, and I cannot guarantee that this will always work. At least until they add other ways to extend the functionality of the knockout kernel.

Looking at the source, I noticed that the params analysis code uses a built-in parser with a knockout. Therefore, if we can somehow connect to the parser, we can configure how the binding strings are interpreted to achieve the desired.

The goal here is to create a new type of binding so that the parsed expression is treated as the actual binding object. It can also be used outside of the component parameters. So we can do this in our / params bindings:

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

Now, anything inside ${ } can be thought of as a binding / params object.

 (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

+4
source

Source: https://habr.com/ru/post/974899/


All Articles