Vaadin elements vaadin-grid custom renderer in API 2+ - javascript

I'm almost done in porting a couple of projects based on vaadin elements
vaadin-grid
from API 1.x to the latest version but I've not found examples or documentation about how to assign a custom renderer to a column.
For example in main.js I can't figure out how to port in API 2+ the following:
grid.columns[2].renderer = function (cell) {
cell.element.innerHTML = '';
var progressBar = document.createElement('progress');
progressBar.setAttribute('value', ((statuses.indexOf(cell.data) + 1) / statuses.length).toString());
cell.element.appendChild(progressBar);
};
The specific problem in here is that in API 2+ columns are undefined
Is it possible to assing custom rendering behavoir to a vaadin-grid-column?
NB: this question is not about vaadin framework but about vaadin elements
Debug session looking for something may help such as TemplateRenderer or similar but I found nothing until now:

The JS API is significantly changed from v1 to v2, and there’s no longer a columns object. Instead, if you want to configure columns using JS, you need to modify the properties of the <vaadin-grid-column> elements directly (you need to have a DOM reference).
For renderers specifically, you use regular HTML in the column template, as mentioned in the migration guide (the Wiki was closed for some reason, I just reopened it).
For your specific code example, it would translate to:
<vaadin-grid>
<vaadin-grid-column>
<template>
<progress value="[[item.value]]"></progress>
</template>
</vaadin-grid-column>
</vaadin-grid>
Replace item.value with the correct property in your data object (or use a computed property if you need to transform the data somehow before passing it onto the <progress> element.
Bonus:
Have you considered using <vaadin-progress-bar> ;)
Valo theme demo: https://cdn.vaadin.com/vaadin-valo-theme/2.0.0-alpha4/demo/progress-bars.html

Related

How to add range filter in vue-tables-2 server side

I'm using a server side's vue-tables-2 component for representing information from the DB. This table contains numeric columns, textual columns and date columns.
My problem is with the numeric columns filtering. I want to add option for range filtering (>,>=,<,<=,=,between, etc).
The only documentation i could find is this:
https://www.npmjs.com/package/vue-tables-2#server-side-filters
Server Side Filters
A. use the customFilters option to declare your filters, following this syntax:
customFilters: ['alphabet','age-range']
B. the same as in the client component.
But i don't understand few things:
Where is 'age-range' implemented?
Where do I specify the filter of each column?
Do i have to use the vuex\ bus?
Can someone please help me with the implementation?
Thanks
Custom Filters are external filters implemented by the consumer of the package. However, they can be embedded in the table instead of the text filter using slots (See Slots documentation).
Since the filter is external to the package, it is your responsibilty to let the package know when it has changed, using either the event bus or Vuex.
In other words, the only interface between the package and the custom filter is the event. The package has no knowledge or control of when or under which circumstances the event is emitted. It is passively listenning for a change and merges the query it receives with the native one.
For example, say you wrote an age-range-filter component that emits a changed event, and you want it to replace the age column native text filter:
<v-server-table ... :columns="['name','age']" :options="tableOptions">
<div slot="filter__age">
<age-range-filter #changed="filter"></age-range-filter>
</div>
</v-server-table>
On your vue instance:
data:{
tableOptions:{
filterable:['name'] // omit 'age' as it will be replaced by your component
customFilters:['age-range']
}
},
methods:{
filter(query) {
VueEvent.$emit('age-range', query);
}
}

Is it possible to server-side render jQuery with ReactJS.Net?

I've been going through this tutorial on ReactJS.NET, and hit a snag. It mentions that:
We will use simple polling here but you could easily use SignalR or other technologies.
While this works when I do client-side rendering, it throws the following error when rendering server-side. Currently, I don't actually need jQuery or SignalR to render the initial state as I'm only using them to subscribe to updates once the app is running. I guess my question is, what is the correct way to structure my React application so that I can render it server-side or client-side at will.
Error while loading "~/Scripts/jquery-1.10.2.js": ReferenceError: window is not defined
Got it working (live demo), I just needed to move the call to React.render outside of the jsx file and pass in what I needed (see snippet below). Another option would be to try and mock the expected objects with jsdom.
<!-- Render the React Component Server-Side -->
#Html.React("CommentBox", new
{
data = Model,
conn = false
})
<!-- Optionally Render the React Component Client-Side -->
#section scripts {
<script src="~/Scripts/react/react-0.12.2.js"></script>
#Scripts.Render("~/bundles/comments")
<script>
React.render(React.createElement(CommentBox, {
data: #Html.Raw(Json.Encode(Model)),
conn: $.hubConnection()
}), document.getElementById("react1"));
</script>
}
Using jQuery while rendering server side using reactjs.net:
The answer is a partial Yes if you put the jQuery in the ComponentDidMount function of React with your setup above.
Like this:
componentDidMount: function(){
if (this.props.userID == 0){
$("#postButton").hide();
}
}
It also worked in some other places but not everywhere. Other places in the React script, I got "ReferenceError: $ is not defined".
Here's some additional comments by the reactjs.net author himself. Basically, jQuery is not designed to work server side so prob best not to rely on it.
https://groups.google.com/forum/#!topic/reactjs/3y8gfgqJNq4
As an alternative, for instance, if you want to control the visibility of an element without using jQuery, you can create a style and then assign the style based on If logic. Then add the style as an inline attribute to the element as shown below. This should work fine in React.
var styleComment = {display: 'block'};
if (this.props.commentCount == 0){
styleComment = {display: 'none'}
}
<div style={styleComment}>Count is greater than 0</div>

Knockout.js - cross-iframe observable binding

I would like to use knockout.js in cross iframe binding. Existence of iframes is dictated by actual app structure I am working on.
This is the scenario (simplified):
Main window: Knockout.js included. window.top.DATA is a global container for data, ex. var DATA = { username: ko.observable('John') };
Module iframe window: Knockout.js also included. View wants do display data stored in window.top.DATA object, using code: <div data-bind="text: window.top.DATA.username></div>
What is the result?
DIV's innerHTML contains ko.observable().toString() contents instead of John.
The cause
Knockout.js is unable to recognize an observable created in parent frame while performing binding, because knockout checks if variable is observable with ko.hasPrototype by comparing references. Since prototypes are different between parent and child frame ko instances, it is impossible to bind values.
Solutions
The simplest solution would be writing something like: window.ko = window.top.ko || setupKO() on the top of script file. Unfortunately, in this case binding like with: window.someLocalObj is referencing to window.top instead of window - we are not able to access local variables and also local templates using template binding.
Another way to fix the problem is simply allow knockout to recognize observables as it should, what would allow observables to track dependency, bind values and just work well. Unfortunately I expect it might be difficult thing to achieve. What options do you see here?
Thank you for all your responses.
Edit
Knockout.js version: 3.2.0.
One solution is to use a single ko instance to handle main window and its frames elements at the same time. iframe elements are acessible through window.frames[frame_index].document:
var DATA = { username: ko.observable('John') };
ko.applyBindings(DATA);
ko.applyBindings(DATA, window.frames[0].document.body);
Working example: Plunker

True custom attributes (e.g. Microdata) in React

The site I am developing makes use of Microdata (using schema.org). As we are shifting development over to use React to render our views I have hit a blocker where React will only render attributes in the HTML spec however Microdata specifies custom attributes such as itemscope.
As I'm relatively new to React and haven't had chance to fully understand the core just yet, my question is what would be the best way to extend the functionality of react.js to allow for defined custom attributes, e.g., Microdata?
Is there a way of extending the attributes/props parser or is it a job for a mixin which checks all passed props and modifies the DOM element directly?
(Hopefully we'll be able to put together a drop in extension for everyone to provide support for this when a solution is clear.)
You can also use "is" attribute. It will disable the attribute white-list of React and allow every attribute. But you have to write class instead of className and for instead of htmlFor if you use is.
<div is my-custom-attribute="here" class="instead-of-className"></div>
Update React 16 custom attributes are now possible
In react 16 custom attributes are now possible
React 16 custom attributes
It looks like these non-standard properties have been added to React
itemProp: MUST_USE_ATTRIBUTE, // Microdata: http://schema.org/docs/gs.html
itemScope: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE, // Microdata: http://schema.org/docs/gs.html
itemType: MUST_USE_ATTRIBUTE, // Microdata: http://schema.org/docs/gs.html
Note that properties have capital letter in the middle:
<div itemProp="whatever..." itemScope itemType="http://schema.org/Offer">
will generate proper lowercase attributes as result.
You should be able to do it with componentDidMount:
...
componentDidMount: function() {
if (this.props.itemtype) {
this.getDOMNode().setAttribute('itemscope', true)
this.getDOMNode().setAttribute('itemtype', this.props.itemtype)
}
if (this.props.itemprop) {
this.getDOMNode().setAttribute('itemprop', this.props.itemprop)
}
}
...
The whole check for Microdata attributes can be wrapped into a mixin for convenient. The problem with this approach is that it won't work for built-in React component (components created by React.DOM). Update: Looking closer at React.DOM, I come up with this http://plnkr.co/edit/UjXSveVHdj8T3xnyhmKb?p=preview. Basically we wrap the built-in components in a custom component with our mixin. Since your components are built upon React 's built-in DOM components, this would work without you having to include the mixin in the components.
The real solution would be injecting a custom config instead of React's DefaultDOMPropertyConfig, however I can't find a way to do so in a drop-in manner (DOMProperty is hidden by the module system).
For those who's still looking for answers:
https://facebook.github.io/react/docs/tags-and-attributes.html
Example:
<div itemScope itemType="http://schema.org/Article"></div>
So far, the best method I've found is based off of some Amp interop code linked from a comment on react's bug tracker thread on the subject. I modified it slightly to work with a newer version of React (15.5.4) and TypeScript.
For regular ES6, you can just remove the type annotation for attributeName. Using require was needed in TS since DOMProperty isn't exposed in react's index.d.ts, but again import could be used in regular ES6.
// tslint:disable-next-line:no-var-requires
const DOMProperty = require("react-dom/lib/DOMProperty");
if (typeof DOMProperty.properties.zz === "undefined") {
DOMProperty.injection.injectDOMPropertyConfig({
Properties: { zz: DOMProperty.MUST_USE_ATTRIBUTE },
isCustomAttribute: (attributeName: string) => attributeName.startsWith("zz-")
});
}
Now you can use any attribute starting with zz-
<div zz-context="foo" />
Normally it'd be a bad idea to use internal parts of react like this, but I think it is better than any of the other methods. It works the same way as existing open-ended attributes like data- and the JSX is even type safe in TS. I believe the next major version of react is going to do away with the whitelist anyway, so hopefully changes won't be needed before we can remove this shim entirely.

Dojo 1.9: Dijit: Disabling option items in a dijit/Form/FilteringSelect that was populated using a store

I am trying to disable option items in a dijit/Form/FilteringSelect control that is populated using a store.
Following this guide: http://dojotoolkit.org/documentation/tutorials/1.9/selects_using_stores/
It seems to be only possible if the Select control was created without using a store. I have deduced this from debugging the FilteringSelect example. I have tried two methods to disable an item:
Following the advice in this thread: How to disable a single option in a dijit.form.Select?. However, the "stateStore" store object in the FilteringSelect example does not have an 'options' property.
Attempting to access the appropriate element in the store object. For example, in the FilteringSelect example, I do the following:
var optionItem = stateStore.get("AZ");
optionItem.disabled = true;
stateStore.put(optionItem);
select.startup();
Neither method seems to work, so it seems that the only way to have disabled items in Dijit Select controls is to use the options property instead.
Thanks in advance for a solution!
There is a difference between the data in your store (which is in fact the business data) and your rendered data (containing view logic). If you use a store, you're actually feeding your rendered data with your store.
To alter the rendered data (= the options in your select), you need to use the getOptions(idx) method of the dijit/form/Select as you can read in the API documentation. To alter the disabled state of the option you can use:
registry.byId("mySelect").getOptions(myId).disabled = true;
That's all you need. Changing the store data won't help, since it represents business data, not view data. I also made an example JSFiddle where the second option is disabled.
for dojo 1.10 and upto 1.x latest version, you need to add a line of code to update the selection UI:
registry.byId("mySelect").getOptions(myId).disabled = true;
registry.byId("mySelect").updateOption(myId);

Categories