Coder Social home page Coder Social logo

flow-components's Introduction

Vaadin Flow Components

This is a maven multi-module project including all vaadin flow components.

main branch is the latest version of all the components that will be released in the Vaadin platform.

Quick start

It's provided a script that facilitates running most common tasks for running or testing components.

Execute ./scripts/run.sh and select the appropriate menu options.

NOTE: a valid unix terminal with a regular shell is needed for running the utility.

Compiling all modules but excluding ITs

  • mvn clean compile -Drelease -T 2C

Compiling all the components and their modules including ITs

  • mvn clean test-compile -DskipFrontend -T 2C

Installing all modules

  • mvn clean install -DskipTests -Drelease -T 2C

Serving the IT pages of a component

  • mvn -am -pl vaadin-checkbox-flow-parent/vaadin-checkbox-flow-integration-tests -DskipTests package jetty:run

Then navigate to http://localhost:8080/vaadin-checkbox/checkbox-test to see the IT page.

Running ITs of one component

  • mvn -am -pl vaadin-checkbox-flow-parent/vaadin-checkbox-flow-integration-tests verify

Running ITs of all components

NOTE: this takes a long while and consumes a lot of resources in your computer, it's better to run tests in the merged repo as it is indicated in the following sections

  • mvn clean verify -T 2C

Merging ITs of all components in one module

There is a able to visit all IT modules and merge then into one unique module. It does substitutions in sources so as routes do no conflict, and also adjust ports etc.

  • ./scripts/mergeITs.js

NOTE: By default it merges all modules, but it's also possible to merge certain modules by passing arguments

  • ./scripts/mergeITs.js button text-field crud

Running ITs of all components in the merged module

It should take around 15-20 minutes depending on the computer capabilities.

  • mvn verify -Drun-it -pl integration-tests

NOTE: that we need to activate the module with the -Drun-it property. By default it runs 4 tests in parallel but you can change it by setting -Dfailsafe.forkCount=5.

Running in Sauce Labs

The time it takes depends on the number of browsers and the modules tested.

To select which browsers to test, set the TESTBENCH_GRID_BROWSERS environment variable with a list of browsers.

TESTBENCH_GRID_BROWSERS=edge,safari-13,firefox

Then run the following command, replacing the *** with your Sauce Labs credentials.

For testing one component run:

  • mvn verify -Dsauce.user=*** -Dsauce.sauceAccessKey=*** -pl vaadin-checkbox-flow-parent/vaadin-checkbox-flow-integration-tests

For running all merged components execute:

  • mvn verify -Dsauce.user=*** -Dsauce.sauceAccessKey=*** -Drun-it -pl integration-tests

Debugging web-test-runner tests of a component

Make sure the root level dependencies are installed

  • npm install

Serve the IT pages of the component whose tests you want to debug

  • See "Serving the IT pages of a component" above

Run the tests for the component once to have the necessary dependencies installed

  • node ./scripts/wtr.js grid

Move to the integration tests module of the component

  • cd vaadin-grid-flow-parent/vaadin-grid-flow-integration-tests

Start the test runner in watch mode

  • npx web-test-runner --playwright test/**/*.test.ts --node-resolve --watch

NOTE: The tests actually import the client module under test from ..integration-tests/frontend/generated/jar-resources. For faster feedback loop you can work on the generated file directly. Just be careful not to lose your changes to it since it's not under version control.

Bumping version for all Maven modules

To update the version for all modules for a new major or minor, run the following command:

mvn versions:set -DnewVersion=<next-version> -DprocessAllModules=true -DgenerateBackupPoms=false

where you replace <next-version> with the version that you want to set.

Build script

The ./scripts/build.sh script is though to be run in CI, it compiles all modules, merge IT's and run those. It expects TBLICENSE and TBHUB variables when run in the CI server. Optionally it's possible to run just a bunch of modules e.g. ./scripts/build.sh grid combo-box

Using the component in a Flow application

To use the component in an application using maven, add the following dependency to your pom.xml:

<dependency>
    <groupId>com.vaadin</groupId>
    <artifactId>vaadin-checkbox-flow</artifactId>
    <version>${platform.version}</version>
</dependency>

Contributing

For submitting pull requests to this repo please check our contributing guidelines.

Update package version for @NpmPackage in all files

There are scripts available for updating the @NpmPackage annotation to its latest patch version:

  • ./scripts/updateNpmVer.js

Modify pom.xml files in modules

In order to align all component buids, maven pom files are generated from templates placed in scripts/templates.

If you need to make any modification in a component, consider whether it is convenient to add the same to all components, then modify files under the template and run:

  • ./scripts/updateJavaPOMs.sh script.

Formatting

Run mvn spotless:apply before pushing your code.

Bug and enhancement tickets

  • Bug tickets and enhancement requests for the web component implementations should go to the Vaadin web components monorepo https://github.com/vaadin/web-components/.
  • Issues that are not component-specific (e.g. requests for new components) or encompass multiple Flow components should be posted in this repository.

LICENSE

For specific module(s), check the LICENSE file under the parent module.

flow-components's People

Contributors

alvarezguille avatar artur- avatar bogdanudrescu avatar caalador avatar dependabot[bot] avatar diegocardoso avatar gilberto-torrezan avatar johannesh2 avatar krissvaa avatar manolo avatar mehdi-vaadin avatar mshabarov avatar mstahv avatar oluwasayo avatar pekam avatar pleku avatar rogozinds avatar shadikhani avatar sissbruecker avatar someonetoignore avatar tatulund avatar tepi avatar tomivirkki avatar ugur-vaadin avatar ujoni avatar vaadin-bot avatar vursen avatar web-padawan avatar yuriy-fix avatar zhesun88 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flow-components's Issues

Changes done in a StartedListener are not shown

Upload upload = new Upload();
upload.addStartedListener(e -> {
    add( new Text("Upload of " + e.getFilename() + " of size " + e.getContentLength() + " started"));
        });

When the upload starts, no text is shown. When the upload is abort or completed, the text is shown.

Disable progress indication

It would be nice to have an ability to disable progress indication for upload.
When user upload too many files it may cause troubles.
For example we have simple code like this:

    Button uploadButton = new Button("upload");
    uploadButton.setWidth("140px");

    Upload upload = new Upload();
    upload.setReceiver(new MultiFileMemoryBuffer());
    upload.setUploadButton(uploadButton);
    upload.setDropAllowed(false);
    add(upload);

    Button test = new Button("foo bar");
    test.setWidth("140px");
    add(test);

The buttons look like this:
selection_018

But if user try to upload too many files the second button go far down:
selection_019

And user has to either reload a page, or close every file's progress, or scroll down.
Would be nice if this could be avoided.

Using a separate data set for the navigator

I'd like to use a custom data set for the navigator, but I cannot assign a class that implements Series (like DataProviderSeries) to Navigator, because it requires a PlotOptionsSeries. On Highstock you can set data property, see documentation and example.
Maybe changing

private PlotOptionsSeries series;

to

private Series series;

could be e reasonable way to implement this feature.
Default series options are:

series: {
    type: 'areaspline',
    fillOpacity: 0.05,
    dataGrouping: {
        smoothed: true
    },
    lineWidth: 1,
    marker: {
        enabled: false
    }
}

and if no data is specified, it takes the first series in the chart.

Reveal password programmatically

Currently there is not API to set the reveal state of PasswordField, which can be useful e.g. when providing the user a password suggestion:

PasswordField passwordField = new PasswordField();
Button suggestButton = new Button("Suggest", event -> {
    String suggestedPassword = generateRandomPassword();
    passwordField.setValue(suggestedPassword);
    passwordField.setReveal(true);
});

Exception occurs when listening to HasSeries events on timeline charts

When a single series is created on a timeline chart as done in this https://github.com/vaadin/vaadin-charts-flow/blob/master/examples/src/main/java/com/vaadin/flow/component/charts/examples/timeline/Candlestick.java#L25-L41 example, Highcharts generates two series: one for the timeline series and another for the navigator. Listening on HasSeries events therefore has the potential of throwing an exception if the event (e.g a mouse over) comes from the navigator.

Redesign of Dialog open / close event handling.

The current event handling of opening and closing a dialog is a little unconvenient.

  1. Developers always have to implement event.isOpened() to check, if the dialog is opened or closed. This forces the developer to either mix open and close logic in one handler or extract the logics to different methods, which is a little contradictory if we could use simple lambda expressions.
  2. DialogCloseAction events are only fired, when closing the dialog by clicking outside or using ESC, but not when using the close() method. Even if it is mentioned in the JavaDoc it is not very intuitive.

This leads to unexpected behavior, when using the API, especially, when someone is new to it and use it by method names.

Dialog should provide a more intuitive and transparent event handling mechanism to allow the registration of dedicated listeners for one of the events.

Consider adding helper methods

When creating a form, I'd like the following helpers:

FormLayout.addBreak(); //adds a <br/> at this location

FormItem.addSpace() or .setSpacing(true); adds a single space character between two items/all items

FormItem.setColspan(int); sets the colspan for the item

FormLayout.addResponsiveStep(<>); adds a step. if list is null, creates an empty list first.

Resetting value to null in CustomValueSetListener don't work

Code to reproduce:

    ComboBox<String> comboBox = new ComboBox<>();
    List<String> values = new ArrayList<>();
    values.add("foo");
    values.add("bar");
    values.add("car");

    comboBox.setItems(values);

    comboBox.addCustomValueSetListener(e->{
        values.add(e.getDetail());
        comboBox.setItems(values);
        comboBox.setValue(null);
    });

Add a random item to comboBox, hit enter, the new item still looks to be selected. In another app it showed a number there, not the previous value (might be different version, the above is tested in this project).

HorizontalLayout.add(Component c) sets new component to index 0 instead of index n

I have a grid inside a horizontal layout. When selecting an entry of that grid an editor component is to be added to the horizontal layout by using .add(...) . (Possible old instances will be removed from this layout by using remove(...) before calling add(...)).

The problem is, that the newly added component is added on the left side of the grid (like slot index 0) instead of right side (like slot index 1). Since in previous Vaadin versions the second case was normal behavior I would expect it here, too.

This screenshot shows the result of adding the editor component (form layout and other stuff) left handed to the grid with the single selection.
image

Selection API

A Java API for setSelectionRange would be very useful for all the Vaadin text fields, e.g.

TextField textField = new TextField();
new Button("Select all", event -> textField.selectAll());

Also access to execCommand could open advanced use cases for the Java API, e.g.

TextField textField = new TextField();
new Button("Copy", event -> {
    textField.selectAll();
    textField.copyToClipboard();
    Notification.show("Copied to your clipboard!");
});

See Clipboard.js for a related JavaScript API.

Support radio button items of type String configured through a template

When creating UI with template, I want to provide the items for RBG via template, because it is easier for me

Given a template like this

<vaadin-radio-button-group id="maybe">
  <vaadin-radio-button value="yes">Yes</vaadin-radio-button>
  <vaadin-radio-button value="no">No</vaadin-radio-button>
</vaadin-radio-button-group>

I'd like to inject a Java component in this this way

@Id("maybe")
private RadioButtonGroup<String> maybe;

and maybe.getValue() should return either null, "yes" or "no" depending on the actual selection.

One way of implementing this would be to add a framework level mechanism for letting an @Id component initialize itself based on how it's defined in the template, and then specifically for this case implement a DataProvider that is backed by the DOM children defined in the template.

Acceptance Criteria

  • There is a demo on supplying the items from the template and just adding a value change listener on server side
    • It should be very clear that only type String is supported

Support for Key events?

Hello,

It seems that Key events are not supported in the Grid but the behaviour is a little bit confusing.
KeyDown events are not supported at all (it is understandable as the propagation is prevented in the web component).

However KeyPress events work mostly fine in Chrome but might not be supported on Firefox.
I say "mostly" because it seems that some keys are not reported (like insert, suppr, etc).

I think it would be useful to let users interact with key events, it would allow them to define rich component behavior on the server-side instead of extending the web component.

What do you think ?

Reuse column value extractor for sorting

Now adding a basic sorting for a column looks like this:

grid
   .addColumn(person->person.getLastName() + ", " +person.getFirstName())
       .addComparator(person->person.getLastName() + ", " +person.getFirstName())

if we reuse column value extractor to create column comparator also, it would look like:

grid
   .addColumn(person->person.getLastName() + ", " +person.getFirstName())
       .setSortable(true)

Cannot attach date-picker from java

Assume the following component structure:
MyView
--MyPolymerComponent created on server
---DatePicker created on server and attached to the component

In such case I got a client side exception:
Uncaught TypeError: Cannot read property 'input' of undefined

Is reproduced in flow spring skeleton.
Tried rc2 and rc3 versions.

opening/closing dialog produces extra request to server

Any request that opens or closes the dialog causes an extra request to server because of the opened-changed listener in Dialog.java constructor. This is very noticeable in slow 3G networks.

Makes not sense that setting the opened property from server side needs an extra request notifying server something that it should already know.

Probably Flow should be aware of this fact and prevent sending standard setters events when changes come from server side.

Related with vaadin/flow#3772

Provide a way to style a content wrapper for the dialog.

If you create a dialog using Java code then the content overlay will contain extra div inside flow-component-renderer.
This div is the container element which is added as a virtual child to the Dialog element in its CTOR :

container = new Element("div");
getElement().appendVirtualChild(container);

when dialog is shown this div becomes a child of the flow-component-renderer element and it wraps the dialog content.
Since this element is internal for Dialog implementation its not possible to access to it anyhow and it's not possible to influence on this element. So you can't style it easily.

It's not clear which API should be used to make it work. We definitely don't want to open this container element as is for developers. So we need provide API which allows somehow to do some restricted number of actions.

See details in vaadin/vaadin-dialog-flow#69.

Add setMargin(boolean)

Add Java API for adding theme specified amount of margin around FormLayout:

public class CustomerForm extends Composite<FormLayout> {
    public CustomerForm() {
        getContent().setMargin(true);

Currently the only way I have found to do this is to wrap the FormLayout e.g. in a VerticalLayout and add the margin there:

public class CustomerForm extends Composite<VerticalLayout> {
    public CustomerForm() {
        FormLayout root = new FormLayout();
        getContent().add(root);
        getContent().setMargin(true);
        // add all content to the inner FromLayout, not directly to the composition root

Grid row details setting as visible hides the previous items every for every 50th item

Description

When trying to set all the detail rows as visible one by one in grids with under 50 items everything works as expected, all 50 items have their details shown.

Every 50 items something unexpected happens. In a grid with 51 items only the 51st will be shown, with 100 items 51st-100th will be shown, with 101 only the last item, the 101st will be shown and so on.

A user should expect that the details shown programmatically should be visible and will not close other detail rows regardless of the number of items in the Grid.

Reproduce the issue

The attached project bug.zip has 3 views to help with debugging this issue :

  1. The default view has a grid with 50 items all working properly and a tab for navigating to a broken view (and back)
  2. The "broken" view has 51 items
  3. experiment/{int} is a parameterized view that takes the number of random items that are placed in the grid to try different scenarios

Receiver InputStream and size

The current Receiver provides the file name and type and wants a OutputStream to write the uploaded bytes to. This is pretty straightforward if writing to disk, using FileOutputStream, but in distributed environments it is common to save binary files directly to database using the streaming capabilities of JDBC drivers (i.e. java.sql.Blob) which needs an InputStream from which reading the bytes and stream them to the database.

Also, the total size of the stream would be useful if known in advance (e.g. Content-Length header in multipart requests).

Starting the upload programmatically

If I set upload.setAutoUpload(false) I have no ways then to start the upload programmatically, but only clicking on the "play" button on the component.

Developers may need to start the upload when the user clicks a global "Send" button in the form.

No way to disallow clearing selected value

<vaadin.version>10.0.0.beta10</vaadin.version>
Even if the ComboBox is set to be required with setRequired(true), it's still possible to clear the selected value with the x checkmark. There should be a way to make a selection mandatory.

Cannot react to list box selection used in a context menu

@azaberlin commented on Thu Mar 15 2018

Description

I created a context menu via flow template as shown in example "Opening and Closing Events" (https://vaadin.com/components/vaadin-context-menu/html-examples#context-menu-advanced-demos).

Since the designer does not allows the linking of the context menu to the Java companion, I tried to link the listbox itself to react on selections with an value change listener.

As a result an exception occured (see attached log file).

log.txt

Request

Please allow either the access (i.e. injection) of sub elements of a template like this listbox per @id annotation or some kind of VaadinContextMenu component that allows some kind of reaction or access to the nested elements.

Versions

Vaadin 10, Beta 2

Relevant code fragments

<link rel="import" href="../../bower_components/vaadin-context-menu/src/vaadin-context-menu.html">
<link rel="import" href="../../bower_components/vaadin-list-box/vaadin-list-box.html">
<link rel="import" href="../../bower_components/vaadin-item/vaadin-item.html">
...
<vaadin-context-menu open-on="click" close-on="none" selector="vaadin-button">
	<template>
		<vaadin-list-box id="optionsList">
			<vaadin-item id="sendMailButton">Send mail</vaadin-item>
			<vaadin-item id="deleteUser">Delete user record</vaadin-item>
		</vaadin-list-box>
	</template>
	<vaadin-button aria-label="Additional options" theme="small" id="optionsButton">
		<iron-icon icon="vaadin:ellipsis-dots-h"></iron-icon>
	</vaadin-button>
</vaadin-context-menu>
@Id("optionsList")
private ListBox<Object> optionsList;


@Legioth commented on Thu Mar 15 2018

Context menu is one of the Vaadin components for which there's not yet any Java API. Because of the way the content is configured in a <template>, Java support is not completely straightforward. Once implemented, we would probably have to use the same kind of workarounds as for <vaadin-dialog>, or alternatively hardcode for using <vaadin-list-box> and have a Renderer API for configuring <vaadin-item> contents.

Using @Id for elements inside an inner <template> is in general an "impossible" task because there's no way of knowing how such elements will be instantiated. As an example, <dom-repeat> will produce multiple copies of each template element. In-depth discussion on this issue can be found in vaadin/flow#2233.

I'm moving this issue to the Flow repository since it's not directly related to any defect or missing feature in the web component itself, and there isn't yet any vaadin-context-menu-flow repository for the Java API.

Column confuses several abstraction levels at once

The original discussion is here vaadin/vaadin-grid-flow#170 (and may be skipped). It's just for the reference.

The problem is : the Grid Column is just an implementation detail right now and may not be used as an API.

Before the ColumnGroup class had been introduced the Column implementation makes sense since column was 1:1 with its abstraction layer.

Now it's not true anymore. There are several "column implementations" per one column concept.
As a result this confuses the overall design and makes very very hard to understand the code and relationships between various parts of the code.

My main concern here: there is no separation of concerns. Components which are internal implementation details are used as a top level abstraction concept.
As a result it's hard to follow the implementation.

Column and ColumnGroup in their current state are components. And those components are internal implementation detail. It should go to the level below which should be quite clear (implementation level).

Column should not be a component anymore. It should be an abstract concept which is used to add a "column" into the grid. So it should accept a value provider which returns an item which needs to be rendered. And it should contain all top level abstraction level methods to do that.

There should be a separate ColumnXXXX class which represents the column implementation (actually only one possible component in the column implementation).
It may share common superclass with ColumnGroup.

Why do I need a column ?
E.g. the API calls like this:

Column<Person> nameColumn = grid.addColumn(Person::getName, "name")
                .setHeader("Name").setSortable(true);

        HeaderRow secondRow = grid.appendHeaderRow();
        secondRow.getCell(nameColumn).setText("a");

Here the column is used an an id. It just represents the column as a top level concept. It has no sense to make this column as a component.

Another issue is the code:

public Column<T> addColumn(Renderer<T> renderer) {
        String columnId = createColumnId(true);

        getDataCommunicator().reset();

        Column<T> column = new Column<>(this, columnId, renderer);
        idToColumnMap.put(columnId, column);

        AbstractColumn<?> current = column;
        columnLayers.get(0).addColumn(column);

        for (int i = 1; i < columnLayers.size(); i++) {
            ColumnGroup group = new ColumnGroup(this, current);
            columnLayers.get(i).addColumn(group);
            current = group;
        }
        getElement().appendChild(current.getElement());

        return column;
    }

Here only the last one "column" is added to the parent. Then why do we need a number of components which are not attached ? As I understand they are created because they have some other "nature" which is involved somehow in other places.
It means that only this nature should be extracted as an abstraction layer and used here. No need to have them as components.

Method AbstractCell::getColumn() is unbelievable confusing. It doesn't return the grid column.
It returns something which is an implementation detail needed to render the cell.
This is exactly why it should go to the level below (implementation level) , separated from the top level API and should not anyhow refer to the Grid::Column but some internal implementation class XXXColumnRepresentationPartYYY or whatever.

As a result: implementation level for the column rendering should be extracted to its own clear abstraction layer. Current column should be on the top abstraction level.
The relationships between those two layers should be clearly defined and easily discoverable (via the implementation contract).

Use Locale for determinating I18N values

After vaadin/vaadin-date-picker-flow#38, the component will have locale support for displaying the selected date value, but it is not applied to the date picker popup, which is localized via the properties in the DatePickerI18N object.

The set locale should be used for figuring out the following properties for the DatePickerI18N object:

  • month names
  • weekdays
  • weekdays short
  • first day of week

Acceptance Criteria

  • the locale set for the component on server side controls the properties described above
  • the user is still able to override those for the I18N object

When creating a button with an icon without text-content, I want to be encouraged to set aria-label for them, so my app can be used by blind people

@pekam commented on Mon Sep 25 2017

If a button contains only an icon without text, screen-readers can't read it and blind users can't know what the button does. For this reason there is the aria-label attribute.

There should be at least a convenience method for setting this value: Button::setAriaLabel(String)

Also it would be good to encourage the use of aria-label when having a button without visible text-content. Maybe replacing the icon-only constructor with Button(Component icon, String ariaLabel) would do the job, but this might be confusing because we have Button(String text, Component icon)


@Legioth commented on Mon Sep 25 2017

@jouni Doesn't vaadin-button automatically set its slot contents as the label?


@jouni commented on Mon Sep 25 2017

Well, define label. It’s rendered inside the button, yes, and screen readers will pick that up nicely. But when there’s only <iron-icon icon="plus"> what does the screen reader announce?


@Legioth commented on Mon Sep 25 2017

Oops. I missed the part in the description that said that this applies when there's only an icon but no text.

Does ariaLabel make sense in this context, or would it be more natural to refer to this as an alt text?

It's also not clear to me whether the label text should be a feature of the button or a feature of the icon component? What about cases when the icon is used on its own instead of inside a button?


@pekam commented on Mon Sep 25 2017

At least currently Icon by itself is just a decorative component, since it doesn't support click listeners. So I think setting ariaLabel for an Icon makes sense only when it's inside eg. Button.

File name not present in the serialized 'upload-success|error|abort' events

@TomiZet commented on Wed Jun 13 2018

Events 'upload-success', 'upload-error' and 'upload-abort' handled by vaadin-upload component are serialized and send to the back-end (BE). But the event.detail.file does not contain name property. Thus the BE has no information about which file upload was aborted. For more details see also vaadin/components gitter, message from 07th June 2018, Question#1


@limonte commented on Wed Jun 13 2018

File objects aren't serializable by default: http://jsbin.com/nuwivexeto/edit?html,js,console,output

I'm not sure which BE you're using and how your FE communicating with the BE, but maybe this workaround will work for your case: https://stackoverflow.com/a/29281243/1331425


@TomiZet commented on Wed Jun 13 2018

Thanks for the reply! By BE I mean vaadin-flow server part of this UI component.. so the problem is not in the component itself, but in the event listeners, which are I guess registered by vaadin-client js library, correct? When debugging this problem I ended up in the obfuscated js code in the VAADIN/static/client and there the file object was serialized and send to the BE. If so, then this issue might be closed and I need to address it for the client library - same would apply also for issue vaadin/vaadin-upload#270.


@limonte commented on Wed Jun 13 2018

Alright, I'll close this issue and vaadin/vaadin-upload#270 for now. Feel free to add comments in future on both issues so we can reopen them and fix issues if there are some.

Changing to a view that has a Grid sends an extra request to server side

When adding a new grid to a view ends sending a redundant request to server.
The cause is that after instantiating and configuring the grid in client side it executes a couple of RPC methods in server setDetailsVisible and confirmUpdate
Issue is very noticeable when running the app in slow 3G networks

In this screenshot you can see that loading indicator is run twice, and there are two XHR in the wire.
Inspecting request payload you can check that the origin are those mentioned RPC.

grid-extra-request

Related with vaadin/flow#3772
Probably those requests might be queued and scheduled to the next user action request.

Grid items details height bug with content loaded asynchronously

Bug occurs in Vaadin 10.0.0.beta3, Chrome and Firefox

When I have grid with item details generator as FlexLayout with asynchronously loaded content, the details have wrong height and row dissapears.

grid = new Grid<>();
	grid.addColumn(SimplePayment::getPaymentStatus).setHeader("Status").setWidth("calc(100% - 100px - 125px)");
	grid.addColumn(SimplePayment::getPaymentAmount).setHeader("Do wypłaty").setWidth("100px");
	grid.addColumn(SimplePayment::getPayoutDate).setHeader("Wypłacono dnia").setWidth("125px");
	grid.setDetailsVisibleOnClick(true);
	grid.setItemDetailsRenderer(new ComponentRenderer<FlexLayout, SimplePayment>(item -> {
		FlexLayout details = new FlexLayout();
		details.addClassName("flex-column");
		UI ui = UI.getCurrent();
		PaymentService paymentService = PortalRest.initClient()
						.build(PaymentService.class);
		VaadinSession current = VaadinSession.getCurrent();
		new Thread(() -> {
			VaadinSession.setCurrent(current);
			List<PaymentComponent> components = paymentService.getPaymentComponents(item.getId(), item.getPaymentType().ordinal());
			ui.access(new Command() {

				@Override
				public void execute() {
					components.forEach(component -> {
						details.add(new Label(component.getName()));
					});
					ui.push();
				}
			});
		}).start();
		return details;
	}));
grid.setHeightByRows(true);
grid.getElement().setAttribute("theme", "compact row-stripes");

Grid before any action:
image
After click on first row:
image
But when I only change browser width, it looks correctly:
image

From JS: Selection events are not always sent to server

If you select/deselect using the JS API:
selectItem / deselectItem, there is no selection change event fired

If you select/deselect using keyboard when focus is on the checkbox (i.e. press enter before space on a multiselect selection checkbox), no selection change event is fired.

Date-picker's value is always changed from client after attach

When the PolymerTemplate with date-picker inside is attached to the view I see in server-side logs that its value was changed twice:

date:  2018-06-11   old:  null
date:  2018-11-06   old:  2018-06-11

Seems that updating locale makes this weird change on client.
As a result it's impossible to use date-picker with binder and to do a dirty checking.

Using Tabs with server-side router

When I'm using Tabs in Flow, I'd like to link each Tab to a certain route, so that I can have each tab bound to a URL and the user can reach the wanted tab easily (e.g. bookmarks).

The use case is to have Tabs in a parent layout, but this also means that when loading a child component the right tab on the parent layout should be selected.

Icons replaced when binding button from polymer template

I have a companion java file with a button binding a vaadin-button in the polymer template like that:

//java file
@Id ("btnActionAdd")
private Button btnActionAdd;
...
btnActionAdd.setText(getTranslation("add.text"));
<!--html file -->
<vaadin-button id="btnActionAdd" theme="small primary">
    <iron-icon icon="vaadin:plus"></iron-icon>
</vaadin-button>

When I'm setting the text for the vaadin-button the method replace the iron-icon for the text only.
The expected behavior will be a button with an iron-icon and the text defined in setText method.

Aborting an upload should not log an error

It is a normal operation for the user to abort an upload, i.e. click the X button next to the file name. Upload should also consider this a normal thing that happens from time to time and should not scream loudly about it. Currently with Jetty you get

[qtp83721081-21] ERROR com.vaadin.flow.server.DefaultErrorHandler - 
com.vaadin.flow.server.UploadException: Upload failed
	at com.vaadin.flow.server.communication.StreamReceiverHandler.streamToReceiver(StreamReceiverHandler.java:427)
	at com.vaadin.flow.server.communication.StreamReceiverHandler.handleFileUploadValidationAndData(StreamReceiverHandler.java:267)
	at com.vaadin.flow.server.communication.StreamReceiverHandler.handleStream(StreamReceiverHandler.java:196)
	at com.vaadin.flow.server.communication.StreamReceiverHandler.doHandleMultipartFileUpload(StreamReceiverHandler.java:181)
	at com.vaadin.flow.server.communication.StreamReceiverHandler.handleRequest(StreamReceiverHandler.java:132)
	at com.vaadin.flow.server.communication.StreamRequestHandler.handleRequest(StreamRequestHandler.java:95)
	at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1516)
	at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:355)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:835)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1685)
	at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:225)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1668)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:581)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1158)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1090)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
	at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:213)
	at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:109)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:119)
	at org.eclipse.jetty.server.Server.handle(Server.java:517)
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:308)
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:242)
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
	at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:75)
	at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceAndRun(ExecuteProduceConsume.java:213)
	at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:147)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:654)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:572)
	at java.lang.Thread.run(Thread.java:745)
Caused by: org.eclipse.jetty.io.EofException: Early EOF
	at org.eclipse.jetty.server.HttpInput$3.noContent(HttpInput.java:791)
	at org.eclipse.jetty.server.HttpInput.read(HttpInput.java:157)
	at org.apache.commons.fileupload.MultipartStream$ItemInputStream.makeAvailable(MultipartStream.java:999)
	at org.apache.commons.fileupload.MultipartStream$ItemInputStream.read(MultipartStream.java:903)
	at java.io.InputStream.read(InputStream.java:101)
	at com.vaadin.flow.server.communication.StreamReceiverHandler.streamToReceiver(StreamReceiverHandler.java:376)
	... 35 more
[qtp83721081-21] ERROR com.vaadin.flow.server.DefaultErrorHandler - 
org.eclipse.jetty.io.EofException: Early EOF
	at org.eclipse.jetty.server.HttpInput$3.noContent(HttpInput.java:791)
	at org.eclipse.jetty.server.HttpInput.read(HttpInput.java:157)
	at org.apache.commons.fileupload.MultipartStream$ItemInputStream.makeAvailable(MultipartStream.java:999)
	at org.apache.commons.fileupload.MultipartStream$ItemInputStream.close(MultipartStream.java:943)
	at org.apache.commons.fileupload.MultipartStream$ItemInputStream.close(MultipartStream.java:922)
	at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl$FileItemStreamImpl.close(FileUploadBase.java:866)
	at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.findNextItem(FileUploadBase.java:1017)
	at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.hasNext(FileUploadBase.java:1106)
	at com.vaadin.flow.server.communication.StreamReceiverHandler.doHandleMultipartFileUpload(StreamReceiverHandler.java:179)
	at com.vaadin.flow.server.communication.StreamReceiverHandler.handleRequest(StreamReceiverHandler.java:132)
	at com.vaadin.flow.server.communication.StreamRequestHandler.handleRequest(StreamRequestHandler.java:95)
	at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1516)
	at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:355)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:835)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1685)
	at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:225)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1668)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:581)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1158)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1090)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
	at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:213)
	at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:109)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:119)
	at org.eclipse.jetty.server.Server.handle(Server.java:517)
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:308)
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:242)
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
	at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:75)
	at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceAndRun(ExecuteProduceConsume.java:213)
	at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:147)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:654)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:572)
	at java.lang.Thread.run(Thread.java:745)
[WARNING] 
javax.servlet.ServletException: com.vaadin.flow.server.ServiceException: org.eclipse.jetty.io.EofException: Early EOF
	at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:357)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:835)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1685)
	at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:225)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1668)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:581)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1158)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1090)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
	at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:213)
	at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:109)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:119)
	at org.eclipse.jetty.server.Server.handle(Server.java:517)
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:308)
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:242)
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
	at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:75)
	at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceAndRun(ExecuteProduceConsume.java:213)
	at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:147)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:654)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:572)
	at java.lang.Thread.run(Thread.java:745)
Caused by: com.vaadin.flow.server.ServiceException: org.eclipse.jetty.io.EofException: Early EOF
	at com.vaadin.flow.server.VaadinService.handleExceptionDuringRequest(VaadinService.java:1565)
	at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1528)
	at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:355)
	... 28 more
Caused by: org.eclipse.jetty.io.EofException: Early EOF
	at org.eclipse.jetty.server.HttpInput$3.noContent(HttpInput.java:791)
	at org.eclipse.jetty.server.HttpInput.read(HttpInput.java:157)
	at org.apache.commons.fileupload.MultipartStream$ItemInputStream.makeAvailable(MultipartStream.java:999)
	at org.apache.commons.fileupload.MultipartStream$ItemInputStream.close(MultipartStream.java:943)
	at org.apache.commons.fileupload.MultipartStream$ItemInputStream.close(MultipartStream.java:922)
	at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl$FileItemStreamImpl.close(FileUploadBase.java:866)
	at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.findNextItem(FileUploadBase.java:1017)
	at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.hasNext(FileUploadBase.java:1106)
	at com.vaadin.flow.server.communication.StreamReceiverHandler.doHandleMultipartFileUpload(StreamReceiverHandler.java:179)
	at com.vaadin.flow.server.communication.StreamReceiverHandler.handleRequest(StreamReceiverHandler.java:132)
	at com.vaadin.flow.server.communication.StreamRequestHandler.handleRequest(StreamRequestHandler.java:95)
	at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1516)
	... 29 more

None of this should be shown. Can be logged on DEBUG level instead of WARNING

"This instance is immutable" exception, when try to set FlexGrow on Text

In Java I wrap a Text component (plus some other components) inside a HorizontalLayout and call setFlexGrow(1, text) for the given Text component. As a result I get an exception.

Code fragment:

Text text = new Text("x");
HorizontalLayout layout = new HorizontalLayout();
layout.add(text);
// ... adding other stuff
layout.setFlexGrow(1, text); // throws exception

Exception:

java.util.concurrent.ExecutionException: java.lang.UnsupportedOperationException: This instance is immutable
	at java.util.concurrent.FutureTask.report(FutureTask.java:122) ~[na:1.8.0_162]
	at java.util.concurrent.FutureTask.get(FutureTask.java:192) ~[na:1.8.0_162]
	at com.vaadin.flow.server.FutureAccess.get(FutureAccess.java:61) ~[flow-server-1.0.0.beta4.jar:na]
	at com.vaadin.flow.server.VaadinService.runPendingAccessTasks(VaadinService.java:1999) [flow-server-1.0.0.beta4.jar:na]
	at com.vaadin.flow.server.VaadinSession.unlock(VaadinSession.java:621) [flow-server-1.0.0.beta4.jar:na]
	at com.vaadin.flow.server.VaadinService.ensureAccessQueuePurged(VaadinService.java:1961) [flow-server-1.0.0.beta4.jar:na]
	at com.vaadin.flow.server.VaadinService.accessSession(VaadinService.java:1927) [flow-server-1.0.0.beta4.jar:na]
	at com.vaadin.flow.server.VaadinSession.access(VaadinSession.java:923) [flow-server-1.0.0.beta4.jar:na]
	at com.vaadin.flow.component.UI.access(UI.java:451) [flow-server-1.0.0.beta4.jar:na]
	at com.vaadin.website.usermanagement.utils.UIAccessor.lambda$runInUI$0(UIAccessor.java:18) [classes/:na]
	at java.util.Optional.ifPresent(Optional.java:159) ~[na:1.8.0_162]
	at com.vaadin.website.usermanagement.utils.UIAccessor.runInUI(UIAccessor.java:18) [classes/:na]
	at com.vaadin.website.usermanagement.frontend.views.users.UsersListView.showChangedDataPopup(UsersListView.java:214) ~[classes/:na]
	at com.vaadin.website.usermanagement.frontend.views.users.UsersListPresenter.onUserDeleted(UsersListPresenter.java:192) ~[classes/:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_162]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_162]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_162]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_162]
	at com.vaadin.events.DefaultPublisher.invoke(DefaultPublisher.java:173) ~[events-core-1.0.0-SNAPSHOT.jar:na]
	at com.vaadin.events.DefaultPublisher.onListenerIteration(DefaultPublisher.java:155) ~[events-core-1.0.0-SNAPSHOT.jar:na]
	at com.vaadin.events.ThreadedPublisher.lambda$onListenerIteration$0(ThreadedPublisher.java:37) ~[events-core-1.0.0-SNAPSHOT.jar:na]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_162]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_162]
	at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_162]
Caused by: java.lang.UnsupportedOperationException: This instance is immutable
	at com.vaadin.flow.dom.impl.ImmutableEmptyStyle.set(ImmutableEmptyStyle.java:38) ~[flow-server-1.0.0.beta4.jar:na]
	at com.vaadin.flow.component.orderedlayout.FlexComponent.setFlexGrow(FlexComponent.java:266) ~[vaadin-ordered-layout-flow-1.0.0.beta2.jar:na]
	at org.vaadin.stefan.UpdaterNotification.addRemovableItem(UpdaterNotification.java:131) ~[updater-notification-1.0.0-SNAPSHOT.jar:1.0.0-SNAPSHOT]
	at com.vaadin.website.usermanagement.frontend.views.users.UsersListView.lambda$showChangedDataPopup$72d56f1c$1(UsersListView.java:217) ~[classes/:na]
	at com.vaadin.flow.component.UI.accessSynchronously(UI.java:390) [flow-server-1.0.0.beta4.jar:na]
	at com.vaadin.flow.component.UI$1.execute(UI.java:454) ~[flow-server-1.0.0.beta4.jar:na]
	at java.util.concurrent.Executors$RunnableAdapter.call$$$capture(Executors.java:511) ~[na:1.8.0_162]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java) ~[na:1.8.0_162]
	at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266) ~[na:1.8.0_162]
	at java.util.concurrent.FutureTask.run(FutureTask.java) ~[na:1.8.0_162]
	at com.vaadin.flow.server.VaadinService.runPendingAccessTasks(VaadinService.java:1996) [flow-server-1.0.0.beta4.jar:na]
	... 20 common frames omitted

add(Tab... tabs) seems unnecessary

Tab is a Component and add(Tab... tabs) only forwards to default void add(Component... components) in HasComponents. Why does add(Tab... tabs) exist?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.