[Autocomplete] Multiple can't pass 'required' validation

[x] The issue is present in the latest release.
[x] I have searched the issues of this repository and believe that this is not a duplicate.

Current Behavior 😯

When submitting a form with an Autocomplete that allows multiple values and that has the 'required' prop on the text input, the validation error shows up whether values were selected or not.

Expected Behavior 🤔

The text field should have some value so that it passes validation on form submit.
Steps to Reproduce 🕹

https://codesandbox.io/s/material-demo-grwoq
Steps:

Create an Autocomplete with 'multiple' prop and pass 'required' to the rendered textfield.
Wrap it in a form with a submit handler.
Try to submit the form

Context 🔦

This is really useful in forms without custom validation.
Your Environment 🌎

Tech
Version

Material-UI
v4.10.2

React

Browser

TypeScript

etc.

What do you think about this fix?
diff --git a/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js b/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js
index feea18c89..577df20a0 100644
--- a/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js
+++ b/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js
@@ -962,6 +962,7 @@ export default function useAutocomplete(props) {
       ref: inputRef,
       autoCapitalize: 'none',
       spellCheck: 'false',
+      ...(multiple && value.length > 0) ? { required: null} : {},
     }),
     getClearProps: () => ({
       tabIndex: -1,

I will work on it!

What do you think about this fix?
diff --git a/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js b/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js
index feea18c89..577df20a0 100644
--- a/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js
+++ b/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js
@@ -962,6 +962,7 @@ export default function useAutocomplete(props) {
       ref: inputRef,
       autoCapitalize: 'none',
       spellCheck: 'false',
+      ...(multiple && value.length > 0) ? { required: null} : {},
     }),
     getClearProps: () => ({
       tabIndex: -1,

In that case what if multiple is false, you can consider a situation when we are passing a Radio component instead of Checkbox in renderOption of AutoComplete. You are allowed to select only one out of all the values in list. In this situation I think the following check ...(multiple && value.length > 0) ? { required: null} : {} wouldn't work.
So we will still get validation error even tough we have already selected one from the list.
However I am not sure if having Radio in Autocomplete sounds practical or not as in that case on would use Select component instead of Autocomplete .

Reopening since #21670 did not address the underlying issue. A fix should be based on #21692 or a similar test.
The issue is that submitting a form is prevented. That should not be solved by removing attributes which affect styling, assistive technology etc.

Could we consider the styling and a11y downside as an acceptable limitation of the tradeoff?

The number of upvotes on 👍 can help understand the pain https://github.com/JedWatson/react-select/issues/1453 around validation.

Could we consider the styling and a11y downside as an acceptable limitation of the tradeoff?

There's no other way than a simple: no. There's too much that goes into this attribute.

@eps1lon Fair enough, it sounds like this issue deserves more attention, I went ahead to quickly.

I have seen https://select2.org/ uses a hidden multi-select behind the scene, maybe we could consider a similar approach.

Any update on this? I was facing the same problem.

Check array for non empty value in required prop works for me
const [value, setValue] = React.useState([])
<Autocomplete
  id="containter-select"
  options={containers}
  getOptionLabel={option => option.name}
  multiple
  onChange={handleSelectChange}
  renderInput={params => (
    <TextField
      {...params}
      label="Контейнер"
      fullWidth
      required={value.length === 0}
      helperText="Выберите контейнер чек-лист"
      variant="outlined"
      size="small"
    />
  )}
/>

@vlados26 While it solves most of the problem, changing the prop also has UI and a11y implications. For instance, it removes the asterisk at the end of the label. It would be better to remove the required attribute on the underlying <input> element. This should be good enough:
/* eslint-disable no-use-before-define */
import React from "react";
import TextField from "@material-ui/core/TextField";
import Autocomplete from "@material-ui/lab/Autocomplete";

export default function CheckboxesTags() {
  const [value, setValue] = React.useState([]);
  return (
    <form>
      <Autocomplete
        multiple
        value={value}
        onChange={(event, newValue) => {
          setValue(newValue);
        }}
        options={top100Films}
        getOptionLabel={(option) => option.title}
        renderInput={(params) => (
          <TextField
            {...params}
            required
            inputProps={{
              ...params.inputProps,
              required: value.length === 0
            }}
            label="Checkboxes"
            placeholder="Favorites"
          />
        )}
      />
      <button type="submit">save</button>
    </form>
  );
}

https://codesandbox.io/s/material-demo-forked-tenix?file=/demo.js:0-897

There is still a problem with this workaround: If you type some junk into the autocomplete without selecting anything and hit return, the form will pass validation and attempt to submit. I don't think this workaround is really a substitute for a proper feature.

There is still a problem with this workaround: If you type some junk into the autocomplete without selecting anything and hit return, the form will pass validation and attempt to submit. I don't think this workaround is really a substitute for a proper feature.

This issue should be reopened as the workaround doesn't solve the problem


Make makefile more idempotent / maybe Make it a taskfile (begginer issue)

Intentionally leaving this vauge: Whoever picks it up can chose how to do it.  Fun issue to start with .   Either

fix the makefile targets so they all work OOTB (for example by running eval "$(curl -sL https://raw.githubusercontent.com/travis-ci/gimme/master/gimme | GIMME_GO_VERSION=1.18beta1 bash)" beforehand ... or confirming GOLang version...
in the process if folks want to get rid of make targets and replace them w/ a Taskfile (taskfile.dev) , and make those work ootb , thats find to

Can someone get these targets all functioning ? or maybe even rewrite it as a https://taskfile.dev/
/good-first-issue

/good-first-issue

/assign

/assign
Hi @adityadtu5, are you still working on this issue? Have you come up with a plan/idea for how to work on it? Are you going to stick with makefiles or rewrite it in taskfiles?

for now, i think running targets one at a time and seeing what works/doesnt and fixing them is a good start.  then can decide on the taskfile part later if we want it

/assign
I'll add some an error when trying to run make tilt-up without previously running make tilt-setup.


"Variable" set for gitea action not accessible in job

Description
When setting a custom variable for gitea action in "repo -> settings -> actions -> variables -> "Variables Management"" it is not accessible in the job.
I have tried ${{VARNAME}}, ${{github.VARNAME}}, ${{env.VARNAME}}, and ${{gitea.VARNAME}}.
act_runner is on a different server.
Gitea Version
1.21.0+dev-437-gb9baed2c74
Can you reproduce the bug on the Gitea demo site?
Yes
Log Gist
No response
Screenshots
No response
Git Version
No response
Operating System
archlinux
How are you running Gitea?
installed gitea-git package from archlinux AUR
Database
SQLite

expression 'echo ${{secrets.DOCKER_PASSWORD}} | docker login --password-stdin --username ${{gitea.DOCKER_USERNAME}} myregistry.com' rewritten to 'format('echo {0} | docker login --password-stdin --username {1} myregistry.com', secrets.DOCKER_PASSWORD, gitea.DOCKER_USERNAME)'
evaluating expression 'format('echo {0} | docker login --password-stdin --username {1} myregistry.com', secrets.DOCKER_PASSWORD, gitea.DOCKER_USERNAME)'
expression 'format('echo {0} | docker login --password-stdin --username {1} myregistry.com', secrets.DOCKER_PASSWORD, gitea.DOCKER_USERNAME)' evaluated to '%!t(string=echo *** | docker login --password-stdin --username  myregistry.com)'

"secrets" work fine via ${{secrets.VARNAME}} but variables dont

${{variables.VARNAME}} doesn't work either:
Unable to interpolate expression 'format('echo {0} | docker login --password-stdin --username {1} myrepository.com', secrets.DOCKER_PASSWORD, variables.DOCKER_USERNAME)': Unavailable context: variables

I see gitea developers themselves use "secrets" to store the DOCKER_USERNAME, because it doesn't seem to work otherways. Why isn't there a disclaimer in "Variables Management" UI?
https://github.com/go-gitea/gitea/actions/runs/5328145644/workflow#L76

Finally found https://github.com/go-gitea/gitea/pull/24724
@sillyguodong can you please improve gitea documentation so that it is clear ${{vars.VARNAME}} needs to be used? It should be said both in the UI at org/reponame/settings/actions/variables and in the gitea docs.

Not sure why for "Variables" the abbreviation is ${{vars.VARNAME}} but for "Secrets" the abbreviation is ${{secrets.VARNAME}}. It should be the same style, either full or abbreviated.


Add psalm linter for PHP

Submitted this previously in #1593, but I didn't follow through with the requested changes and it was closed for inactivity. This time, I added the documentation.

All right! I believe I've addressed all your comments.
I really admire your project by the way. The documentation and tooling around contributing is extremely impressive.

Anything else before this is ready to merge, @w0rp ?


Problem with large message

I tried to sent a large message(1-2MB) and didn't work. I believe that happen because of "max.request.size" property. I looked in code after this property, or where i can put it, but i didn't figure it out. It's possible to send a message bigger than 1-2MB? If yes, where i have to put that property?
Thanks

There is no maximum message size limit on our side, this may be a setting on your broker. Or also a bug!


CAMEL-18736: Ensure cxfEndpoint schemas are uniquely named for JaxRS and JaxWS to avoid classpath conflicts

Prevent classpath conflicts occurring when both camel-cxf-spring-soap and camel-cxf-spring-rest modules are included in a spring boot application, and the spring schemas are loaded.
I wasn't able to think of a sensible test for this change, but all existing tests pass and a local build of this resolves our issue

The public namespaces are not affected so Camel end users should not have anything to change in their applications.


Tauri Support

Does Velopack support Tauri?
I'm hitting the NSIS 2GB limit and was wondering if Velopack could be a solution.
https://github.com/tauri-apps/tauri/issues/7372

Velopack should be good for around 5-6GB, don't remember exactly where things start falling over. I am confident that can also be improved.
So the answer is "theoretically yes!". Velopack is pretty opinionated and generally wants to be your installer and updater.. so it would replace NSIS but I know Tauri has some built-in updating...
You might need to switch to Velopack's updates (From the tauri plugin) in the short term to use our installer.


How to test components with react-click-outside

When a component is exported with enhanceWithClickOutside, enzyme can't find the component in it.
For example, the following fails:
test('Renders the root div', () => {
  const component = shallow(<MyComponent />);
  expect(component).toContain('div#root-div');
});

MyComponent.js
function MyComponent() {
  // ...
  return (
    <div id="root-div">
      {/* ... */}
    </div>
  );
}
export default enhanceWithClickOutside(MyComponent)

What is the workaround?

This is a general issue with higher order components. Better to ask at the enzyme project.
Resources:
https://github.com/airbnb/enzyme/issues/539
https://github.com/airbnb/enzyme/blob/e7226255bded93e285e36b50e16b59c8dc2458f9/docs/api/ShallowWrapper/dive.md

@nerdymax We don't use enzyme but you may find PR #25 and Issue #20 helpful for the approach we've taken.


Getting scroll position of CodeArea

Hi!
I'm using this API for a project, and have added a CodeArea in a StackPane on top of a Canvas. I want to scroll the Canvas with the CodeArea. Is it possible to get the scroll position of the CodeArea to let me do this?
Thanks!

Hey Tomas,
Did anything ever come out of the conversation about the "Control<T extend Skin>" suggestion in The trouble with Skins?

None that I know of. I plan to remove the whole skin thing from RichTextFX whenever I can get around to it. There just doesn't seem to be any benefit to using a skin. No one is ever going to write a custom skin for RichTextFX, anyway.

Any update about this?
Also, considering the number of issues that are currently open, the other work you are doing elsewhere, the difficulty of fixing this issue, and the length with which this has been open, how important this is to you?

Refactoring to get rid of the skin, and thus opening the way to view-specific features like this one (but also many others) is definitely something I want to do. At the same time, as you noticed, I have other work to do elsewhere, and this isn't exactly a pressing issue for me.
Regarding open issues, vast majority of them are feature requests. I try to resolve bugs quickly.
I must admit that so far I haven't done a very good job of steering the community to get more involved with the RichTextFX codebase and make substantial contributions. (There were some nice contributions like xml highlighting demo and text background color, but that's about it.)

Regarding difficulty, both finally getting rid of the skin architecture and then subsequently exposing api for scroll position (given that it will only be an estimate, anyway - see point 2. of my first comment) are relatively easy tasks (although tedious). The fact that we would only get an estimate limits the usefulness of this feature, and is the reason why I don't find it very important.

Yes, thank you for fixing the bugs so quickly!
One reason I haven't contributed code before is that I'm still learning many things about how JavaFX works and how to properly program something (If I was smarter, I would have probably bought a book that explained it in more depth than just the tutorials on oracle). Since this control is complex, I also haven't studied it in-depth and become familiar with how it works.
So, you want to and are able to expose the scroll API relatively easily, but you don't see the point in doing so since its functionality would be limited by the font size and line wrapping. Beside that, you don't personally need the feature, and the world isn't going to end if you don't do this. :-)
The following is me thinking outloud:
As for the issue itself, I guess, assuming that line wrapping is on, the code would need to calculate how wide a line is, then calculate how many lines it should use to display that one line based on the control's width. After that, it would need to calculate the height of each of these lines probably by checking each style used in every segment of that line. Once calculated, this new value, along with every other height value and the constant line spacing value for every line minus one, would be summed up into the scroll value's max. Then the scrollbar's display would need to be adjusted to accordingly.
However, I'm not sure how the line's width could be calculated. The easy way is to display the line itself, but that can't be done in this case. Monospace could be used, but that would limit the font-family used. Besides, CodeArea would already do most of this anyways...
Even if the code were to display the entire document once, calculate its height, remove the document and just display whatever fits inside Flowless, any modifications to the document programmatically wouldn't be accounted for.
Does that sound about right?

That sounds about right, except I wouldn't bother computing the width and subsequently the height of the paragraph (wrapped line) myself. For a given width, TextFlow.prefHeight(width) computes that. The problem is that this can already be quite expensive for very large documents.
Anyway, the place to implement this would be Flowless.
One could come up with some sophisticated algorithms, where the scroll position starts with an estimate (as it does now), and then in the background gradually improves the estimate. This would result in some flickering of the scrollbars before reaching the exact value, but that might be acceptable.

I wouldn't bother computing the width and subsequently the height of the paragraph (wrapped line) myself. For a given width, TextFlow.prefHeight(width) computes that.

Lol... I should have known...
In my program's specific use case, I don't use line wrapping, and the font size is the same for the entire document. Although I might use different font families for the font, the estimate for the scroll value would be accurate in that case, right?
I'll open an issue in Flowless for this.

Yes, in that case the estimate would be accurate, so it is a matter of exposing totalBreadthEstimateProperty() and totalLengthEstimateProperty().

Just an update about this issue: the next version of Flowless (to be released soon) now exposes its scrolling API. Once released, it shouldn't take too long to further expose the API in RichTextFX.

@TomasMikula In my first draft of exposing the scrolling API, I've come across a problem that I'm not quite sure how to resolve. I'm guessing you can further point me in the right direction. I think this might be another Skin-related problem.
Exposing totalHeight/WidthEstimate isn't an issue. However, I'm not sure how to handle the estimatedScrollX/Y values. Getting their values is easy using properties, but I'm not sure how to set them.
Any ideas?
Strategy 1: using properties & action method cannot work due to no VirtualFlow reference. Adding that reference would break Separation of Concerns.
StyledTextArea source code example:
private final Val<Double> estimatedScrollX
public Val<Double> estimatedScrollXProperty() { return estimatedScrollX; }
// ... other code ...
public scrollXToPixel(pixel) {
    // would be "virtualFlow.scrollXToPixel(pixel);" because setting the value of
    //   length/breadth correctly requires calling "setLength/BreadthOffset()"
    //   However, reference to virtualFlow is not available..
}

StyledTextAreaView source code example:
// during constructor process
area.estimatedScrollXProperty().bind(virtualFlow.estimatedScrollXProperty());

Strategy 2: Use just 1 property and bind bidirectionally. Getting value works fine, but no longer able to call the right setter method.
StyledTextArea source code example:
private final Val<Double> estimatedScrollX
public Val<Double> estimatedScrollXProperty() { return estimatedScrollX; }
public double getEstimatedScrollX() { estimatedScrollX.get(); }
public void setEstimatedScrollX(double value) { estimatedScrollX.set(value); }

StyledTextAreaView source code example:
// during constructor process
area.estimatedScrollXProperty().bindBidirectional(virtualFlow.estimatedScrollXProperty());
// whenever program sets area's estimatedScrollX property with new value,
//   virtualFlow's scrollXToPixel(pixel) method is no longer called,
//   which corrupts breadthOffset and makes its value inaccurate.

Strategy 3: Use 2 properties: a getter property & a setter property. Seems like smelly code to me.
StyledTextArea source code example:
private final Val<Double> estimatedScrollX
public Val<Double> estimatedScrollXProperty() { return estimatedScrollX; }

private final Var<Double> scrollXSetter
Var<Double> scrollXSetterProperty() { return scrollXSetter; }
public void setScrollXToPixel(double pixel) { scrollXSetter.set(pixel); }

StyledTextAreaView source code example:
// during constructor process
// getter is bound to actual value
area.estimatedScrollXProperty().bind(virtualFlow.estimatedScrollXProperty());
// setter's changes updates the actual value
area.scrollXSetterProperty().values().subscribe( v -> virtualFlow.scrollXToPixel(v) );

So I suppose that to make Strategy 2 compile, you updated virtualFlow.estimatedScrollXProperty() to return a Var so that it is settable, am I correct? And it somehow works, but is inaccurate? This looks like the difference between a position and pixel offset—they are not the same thing. Turns out virtualFlow.estimatedScrollXProperty() is not pixel offset, but an abstract position, the same kind of thing that scrollbars use. If your content is 1000px long and the position ranges between 0.0 and 1000.0 (could as well be 0.0-1.0, it is not directly related to pixels) and you scroll to the end, your position will be 1000.0 (because you are at the end), but your pixel offset will be, say 600, if your viewport is 400px long.

I found that confusing when implementing VirtualFlow, but had to do that, because that's how scrollbars work.

These strategies were proposed, not tested. I didn't know about the pixel offset, but I can see why that would be confusing. Knowing that now, I think my assumption is a bit mistaken:

I assumed that Strategy 2 wouldn't ultimately work because if a user could set the estimatedScrollX value to an impossible value, it would screw up the visual (somehow). For example, if the user sets the value to -30.0 or 50 pixels beyond the width, wouldn't that screw up the visual? I didn't test that out personally to see what would happen, only assumed that there would be a better way to handle it somehow.

Now that you've explained the pixel offset part, I guess the horizontal scrolling position (if greater than 0) would only show extra white space. However, if set to some negative value, what would happen then?
I'm not sure if the following idea has been created/implemented before in some other form (or even if the idea below is useful in this context), but what if there was a Property class that, when its setValue(value) method is called, it applies some function to value first and then sets its actual value to the result of that function? So something like:
class FunctionalDoubleProperty {
    private double value
    // some functional interface thing (not as familiar with lambdas, sorry...)
    private function

    public double getValue() { return value; }
    public void setValue(double newValue) {
        double oldValue = getValue();
        double toBeSetValue = function.apply(newValue);
        // fire value change events
        fireValueChangeEvent(oldValue, toBeSetValue);
        value = toBeSetValue;
}

I guess the FunctionalDoubleProperty wouldn't be particularly helpful in this context because the function to call would be an instance method from VirtualFlow. Furthermore, the property, when constructed, wouldn't have access to VirtualFlow to assign such a method anyways...

Well, to get around the negative value (duh...):
    public final void setEstimatedScrollX(double pixelOffset) {
        if (pixelOffset < 0) pixelOffset = 0;
        estimatedScrollX.setValue(pixelOffset);
    }

I'm going to test out Strategy 2 by changing Flowless locally according to what you thought I had already done, and see what happens when the scrollX value becomes bigger than the actual width of VirtualFlowContent.

So, Strategy 2 actually does work to an extent. Setting the values negatively or beyond the actual width/height displays the scrolling correctly: if negative, it visually scrolls to 0.0; if positive and beyond its actual w/h, it visually scrolls to the bottom/right fully.
However, the getEstimatedScrollX/Y value will return a false value. For example, if I set the estimatedScrollX value to 50,000 despite the actual width only being 200 pixels and then call getEstiamtedScrollX(), the returned value will be 50,000. If the value is limited by the totalWidthEstimate, it might be more accurate, but it also might prevent a user from fully scrolling to the right.
In some ways, it might be better to create another area class that can set/get the now-exposed scrolling API. The area would be configured to adhere to the no-line-wrapping and same-font-size restraints. Then, such checking and handling would make more sense, and other users of the code that don't need this wouldn't be bothered by it.

So, the scrolling API is basically exposed, but I was testing out what it would be like to bind a StyledTextArea to a scrollPane. When all values (vvalue, hvalue, vmax, hmax) were bound unidirectionally to area's corresponding values, the scrollPane's scrollBar flickered multiple times very rapidly (though this could have been due to the way I was testing this out).
Then I tried something else and encountered a problem. If a user scrolls in either VirtualFlow or the scrollPane, both hvalue & estimatedScrollX need to be updated to the same value (the same goes for vvalue & estimatedScrollY). Unfortunately, I cannot bind these corresponding properties bidirectionally:

area.estimatedScrollXProperty().bindBidirectional(scrollPane.hvaleProperty()); doesn't work because Var's bindBidirectional(Property<Double>) cannot be applied to DoubleProperty.
Likewise, scrollPane.hvalueProperty().bindBidirectional(area.estimatedScrollXProperty()); doesn't work because DoubleProperty's bindBidirectional(Property<? extends Number>) cannot be applied to Var.

When I tested what changing area's estimatedScrollX from type Var to DoubleProperty would look like, I discovered that it would carry this type issue down into Flowless' Sizetracker.
So, a few possible ways this could be fixed:

at SizeTracker's level
if possible, add another bindBidirectional() method to Var that accounts for this issue

For example, if I set the estimatedScrollX value to 50,000 despite the actual width only being 200 pixels and then call getEstiamtedScrollX(), the returned value will be 50,000.

It might be that VirtualFlow's estimatedScrollX does get updated to 200, but it is not propagated through the bidirectional binding. Can you test that by setting VirtualFlow's scrollX way beyond the width?
If you want to use StyledTextArea in a ScrollPane, then you just want the StyledTextArea laid out to its full size (totalWidthEstimate x totalHeightEstimate) and let ScrollPane handle the scrolling. As a start, I would just try binding StyledTextArea's prefWidthProperty and prefHeightProperty to totalWidthEstimate and totalHeightEstimate, respectively.

It might be that VirtualFlow's estimatedScrollX does get updated to 200, but it is not propagated through the bidirectional binding. Can you test that by setting VirtualFlow's scrollX way beyond the width?

I'm not sure I understand what you mean because that was what I was trying to do with the example you quoted. Perhaps I wasn't very clear in describing it.
The goal was to create an area with some amount of text that requires the horizontal scrollbar to appear. So, if the actual width of the area was 200 pixels (or something higher), and I set the estimatedScrollX to 50,000, it would scroll just enough to the right so that the last character is visible, but wouldn't scroll any farther than that. However, if I later got estimatedScrollX, it would still hold the original 50,000 value. The same would go for any negative values: it would scroll so that the leftmost character was visible, but the getEstimatedScrollX() method would return a negative value.
So, I limited it like so:
public void setEstimatedScrollX(double value) {
   if (value < 0) value = 0;
   if (value > getTotalWidthEstimate()) value = getTotalWidthEstimate();
   estimatedScrollX.set(value);
}

The only issue with the above solution is if totalWidthEstimate is inaccurate. Then, this limiter would actually prevent scrolling to the end. Such an inaccuracy would only arise if the code doesn't adhere to the two constraints (no line wrapping & same sized font used throughout entire area).

If you want to use StyledTextArea in a ScrollPane, then you just want the StyledTextArea laid out to its full size (totalWidthEstimate x totalHeightEstimate) and let ScrollPane handle the scrolling. As a start, I would just try binding StyledTextArea's prefWidthProperty and prefHeightProperty to totalWidthEstimate and totalHeightEstimate, respectively.

My idea is to have a ScrollPane besides the StyledTextArea where the contents of the left scrollPane line up horizontallly with the lines of StyledTextArea. The content in the left ScrollPane is too complex to use a ParagraphGraphicFactory to do the same thing:
|--- ScrollPane ----|---- StyledTextArea -----|
|...... content ....... | .......... content ............ |

...... content .......
.......... content ............

If worse comes to worse, I could encapsulate the StyledTextArea inside a ScrollPane and bound it like the way you suggested; however, it would unnecessarily remove the memory optimization that VirtualFlow provides.

BidirectionalBinding.bindNumber(area.estimatedScrollXProperty(), scrollPane.hvalueProperty());
BidirectionalBinding.bindNumber(area.estimatedScrollYProperty(), scrollPane.vvalueProperty());

This works, but it's via the com.sun.javafx package, which if I remember correctly will be unavailable in java 9's modularization, right?

What I meant was to try it on VirtualFlow directly (i.e. without the proxy property on StyledTextArea):
virtualFlow.estimatedScrollXProperty().setValue(50000);
virtualFlow.estimatedScrollXProperty().getValue(); // does it return 50000 or 200?

Here's how I tested this. StyledTextArea had 1000 lines of the same font size added to it, and the first line had a 1000 "hello"s added to it on the first line.
When StyledTextAreaView was constructed...
area.addEventHandler(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
    @Override
    public void handle(KeyEvent event) {
        double d = virtualFlow.totalWidthEstimateProperty().getValue() * 2;
        System.out.println("Setting x to " + d);
        virtualFlow.estimatedScrollXProperty().setValue(d);
        System.out.println("post setting: " + virtualFlow.estimatedScrollXProperty().getValue());
    }
});

After pressing the RIGHT key, the printed output was:
Setting x to 322203.0
post setting: 161101.5

Thanks! So it works, it does not stay set to 322203.0. So my hypothesis was correct, it just does not propagate through the bidirectional binding. This is why I try to avoid bidirectional bindings—because recursive updates are suppressed.

Mm... ok. So that's what's going on.
How hard would it be to create a binding that does do recursion? I'm not
sure if one of your libraries already does that.
On Oct 30, 2015 12:37 PM, "Tomas Mikula"<EMAIL_ADDRESS>wrote:

Thanks! So it works, it does not stay set to 322203.0. So my hypothesis
was correct, it just does not propagate through the bidirectional binding.
This is why I try to avoid bidirectional bindings—because recursive updates
are suppressed.
—
Reply to this email directly or view it on GitHub
https://github.com/TomasMikula/RichTextFX/issues/98#issuecomment-152630049
.

You can simulate one this way:
Var<Double> p;
Var<Double> q;

p.values().feedTo(q);
q.values().feedTo(p);

I am ignoring the Subscription here returned from feedTo, but they should be stored and unsubscribes in StyledTextAreaView#dispose.

So to fully bind a scrollPane to a VirtualFlow through the StyledTextArea as a proxy, I would need to simulate a recusion binding twice, right? Something like this?
In StyledTextAreaView, do as you've shown above so that virtualFlow will correct area's estimatedScrollXProperty:
area.estimatedScrollXProperty().values().feedTo(virtualFlow.estimatedScrollXProperty());
virtualFlow.estimatedScrollXProperty().values().feedTo(area.estimatedScrollXProperty());

And in the place where I'd used StyledTextArea, simulate a recursive bidirectional binding.
area.estimatedScrollXProperty().values().feedTo(scrollPane.hvalueProperty());
Var.doubleVar(scrollPane.hvalueProperty()).values().feedTo(area.estimatedScrollXProperty());

Testing out the above seemed to work fine.

Yeah, you're right, you then need to do it twice.

Turns out the simulated recursive bidirectional binding leads to a side-effect.
If I press and hold a letter, so that it repeatedly inputs that letter into the text, then when the caret goes too far to the right, so that the view should auto-scroll so as to continue letting me see what I'm typing, it doesn't auto-scroll.
The issue lies in StyledTextAreaView's Constructor code where I would write:
area.estimatedScrollXProperty().values().feedTo(virtualFlow.estimatedScrollXProperty());
If this line is commented out, the view will auto-scroll as before. This side-effect does not happen with estimatedScrollYProperty()

I also would like some way to get access to the scrollpane (or equivalent).  My use case is a visual diff program where I would like to have two CodeAreas side by side and synchronize the scrolling between the two.

This, too, is already possible with the snapshot release, where we abandoned the use of skin, and decoupled from the scroll pane from the rest.

I tried building the latest source, scroll bars were broken. They didn't appear at all. I believe the issue is already reported. My CodeAreas are in a SplitPane.  Perhaps I didn't look hard enough for access to the scrolling after discovering that.

scroll bars were broken. They didn't appear at all.

@swpalmer In snapshot version you must wrap text area into VirtualizedScrollPane to get scrollbars.

Or use the factory method AreaFactory. embeddedCodeArea().

I tried building the latest source

Snapshots are also published to the Sonatype repository and should work with a Maven/Gradle build.

Early feedback on this new API is very appreciated.

@TomasMikula After using this API for a while on demos and whatnot, I'm not sure if the API for AreaFactory is that useful largely because I can't modify the underlying area before it gets embedded in the VirtualizedScrollPane. For example, this has more boilerplate...
VirtualizedScrollPane<CodeArea> pane = AreaFactory.embeddedCodeArea();
// tedious boilerplate just to modify the area
CodeArea area = pane.getContent();
/* modify area here.... */

Scene scene = new Scene(pane, /* dimensions */);

... than this:
CodeArea area = new CodeArea();
/* modify area here.... */

Scene scene = new Scene(new VirtualizedScrollPane<>(area), /* dimensions */);

Perhaps if we added a Consumer<AreaType> as a parameter, this wouldn't be as tedious.
Additionally, part of the idea behind AreaFactory was to clone an area. However, now that an EditableStyledDocument is public, the clone methods in the factory are somewhat irrelevant.
IMHO, I no longer think AreaFactory should exist. My only concern with going in that direction is it's not immediately obvious to new users why the ScrollBars don't appear (unless of course they read the javadoc). This concern will weaken over time as the newness of the idea becomes more of the norm.

Should we then remove the cloning methods and move the remaining ones to the respective classes (StyledTextArea, CodeArea, ...)?

Should we then remove the cloning methods and move the remaining ones to the respective classes (StyledTextArea, CodeArea, ...)?

AreaFactory has 3 methods for each of the area:

Cloning methods
Constructor methods
Embedding methods (embed original / embed a cloned version of an area / embedded area)

There's no longer any point to having the cloning methods.
I'm assuming we'd remove the constructor methods (what's the point of writing CodeArea.newInstance(/* args */); as opposed to new CodeArea(/* args */);)? Those were really only there to conveniently provide a common place to construct an area.
In that case, we'd only have embedding methods and I don't see the point of doing that. Subclasses (specifically, the three flavors in RTFX) of StyledTextArea would have type issues with those methods.
For example, I'm guessing the API would look like
class StyledTextArea<PS, S>  {
    public VirtualizedScrollPane<StyledTextArea<PS, S>> embed() {
        return new VirtualizedScrollPane<>(this);
    }
}

In which case, there would be a conflict with StyledTextArea#embed.
class InlineCssTextArea extends StyledTextArea<String, String> {

    // Compiler: incompatible return types
    //  "InlineCssTextArea" should be "StyledTextArea<PS, S>"
    VirtualizedScrollPane<InlineCssTextArea> embed() {
        return new VirtualizedScrollPane<>(this);
    }
}

I was thinking we would move the static embedding methods to the respective classes and keep them static. Making them instance methods might work, too, if the signature is
public VirtualizedScrollPane<? extends StyledTextArea<PS, S>> embed();

and overridden in subclasses to return a more specific type.
You have a point the the utility of these methods is questionable, though.

static embedding methods to the respective classes and keep them static. Making them instance methods might work, too, if the signature is

I was wondering if using a generic like that would prevent such an issue. So, that could work.
There's another subtle factor to consider.
Since a node can only be in one other node's children at a time, if a developer uses embed() twice mistakenly, the first pane won't have the area anymore. In JavaFX, it's always the node's parent that removes a node from its children, but this API would allow a child to remove itself from its parent, which isn't done elsewhere in JavaFX (AFAIK).

I agree. So static factory methods it is?

Sounds reasonable to me.

Actually, is it?
There's two ways of writing the code:
// Given an area...
CodeArea area = //;

// Current API: wrap in a VirtualizedScrollPane
new VirtualizedScrollPane(area);

// New API ? : use a static factory method ?
CodeArea.embed(area);

I guess using static factory methods would only have 2 benefits:

It's shorter than the current API
People are more likely to find the embed method since it's in the same class than VirtualizedScrollPane. We could link to it via javadoc, but we already do that with VirtualizedScrollPane.

Additionally, we haven't yet figured out the utility of these factory methods.

I thought we would just move the factory methods as they are, i.e.
class CodeArea {
    public static VirtualizedScrollPane<CodeArea> embeddedInstance();
}

Ah... those factory methods. ok.

I'm not sure whether you agree or not, but I still think the Consumer<AreaType> should be included. So how about this?
public static <PS, S> VirtualizedScrollPane<StyledTextArea<PS, S>> embeddedInstance(
        Consumer<StyledTextArea<PS, S>> modifier,
        PS initialParagraphStyle, BiConsumer<TextFlow, PS> applyParagraphStyle,
        S initialTextStyle, BiConsumer<? super TextExt, S> applyStyle,
        boolean preserveStyle
) {
    StyledTextArea<PS, S> area = new StyledTextArea<PS, S>(
            initialParagraphStyle, applyParagraphStyle,
            initialTextStyle, applyStyle, preserveStyle
    );
    modifier.accept(area);
    return new VirtualizedScrollPane<>(area);
}

IDK, I probably wouldn't try to get too sophisticated here. For me, the main reason for these factory methods is to provide a simple and straightforward path for migration from 0.6.10 to 0.7, while preserving the behavior. Like "replace this constructor with this factory method and your area will keep having scrollbars as before."

Why not do both? For example, InlineCssTextArea could have 4 static factory methods:
// 2 normal constructors, no modifications
public static VirtualizedScrollPane<InlineCssTextArea> embeddedInstance()
public static VirtualizedScrollPane<InlineCssTextArea> embeddedInstance(String initialText)

// 2 normal constructors, with modifications post area creation
public static VirtualizedScrollPane<InlineCssTextArea> embeddedInstance(
    Consumer<InlineCssTextArea> modifier
)
public static VirtualizedScrollPane<InlineCssTextArea> embeddedInstance(
    String initialText,
    Consumer<InlineCssTextArea> modifier
)

See #304. Looks like we'll be keeping things mostly the same due to the issues I found there.

I tried binding estimatedScrollY of two CodeAreas together so they would scroll together. Both had the same number of lines. It worked very poorly, lots of flickering and jumping. At the ends of the scroll range things weren't in sync but would snap to the right position if somehow another scroll event happened or something like that.

@swpalmer Is it for CodeAreas with scrollbars (i.e. inside VirtualizedScrollPane) or without? Is word-wrapping on or off? Does the behavior improve when synchronizing (i.e. binding) only uni-directionally?

Inside VirtualizedScrollPane. No word-wrap. One-way binding may reduce the flickering a little but does not make the problem go away.

Does the behavior improve without VirtualizedScrollPane?

@swpalmer I had a situation where I wanted to sync the scrolling between a VirtualizedScrollPane and a regular ScrollPane. I couldn't bind them bidirectionally because of a type conflict (VSP: Double; SP: Number). So, the solution Tomas suggested then was to use a simulated recursive binding (e.g. feeding values to one another). If his options don't work, perhaps doing something similar might:
VirtualizedScrollPane<CodeArea> pane1 = //;
VirtualizedScrollPane<CodeArea> pane2 = //;

// simulated recursive binding
Subscription sub = Subscription.multi(
    pane1.estimatedScrollYProperty().values().feedTo(pane2.estimatedScrollYProperty()),
    pane2.estimatedScrollYProperty().values().feedTo(pane1.estimatedScrollYProperty())
);

If that doesn't work, @TomasMikula would we be able to fix this by adding some sort of syncing option in Flowless?

Since the issues remain with just one-directional syncing, I don't think that is the core of the problem. Let's wait for @swpalmer's answer whether the problem remains when no VirtualizedScrollPane is used.

So this has been released in 0.7-M1. @swpalmer please open a new issue for the flickering problem.

Well without VirtualizedScrollPane the testing becomes more difficult without scrollbars... but basically we are seeing nonsensical values for the scroll positions.  They flicker all over the place while dragging a scrollbar, and when we set the scroll position of one pane in response to the change in the other, the change doesn't take right immediately anyway.
I've tried bindings, listeners, and the Subscription stuff mentioned above.
I will open a new issue.


Example code does not work / compile

Type of issue
Code doesn't work
Description
[Enter feedback here]
AbsoluteLayout.Add(new BoxView // I've replaced AbsoluteLayout with my own element, but that's not the problem
{
Color = Colors.Silver
}, new Rect(0, 10, 200, 5));
does not compile or run.  "CS1501: No overload for method 'Add' takes 2 arguments."
Suggestion:
Rather than packing a bunch of statements with implied but not explicit functionality into terse code, it would be FAR more helpful to understand (and see in an example) exactly what elements are being assigned to.  Does the rect correspond to AnchorX, AnchorY? There's no way to make heads or tails out of the "equivalent" XAML here. The XAML example tells you explicitly what is being assigned to:

However if I try to do:
Rect r = new Rect(0, 10, 200, 15);
AbsoluteLayout.LayoutBounds(r); // CS1061: Boxview does not contain a definition for LayoutBounds...
This is VERY frustrating when:
a) The official documentation example does not work and
b) The naming convention between XAML and the "corresponding" methods don't align and
c) Reasonable guesses (which should never be needed in the first place) don't work
[editing to add this]
Here's what DID eventually work:
BoxView goldBoxView = new BoxView
{
Color = Colors.Gold,
};
DrawingCanvas.Add(goldBoxView);   // DrawingCanvas is my XAML AbsoluteLayout element.
Rect r = new Rect(0, 10, 200, 5);
DrawingCanvas.SetLayoutBounds(goldBoxView, r);
goldBoxView.GestureRecognizers.Add(pointerGestureRecognizer);  // Playing around with pointer detection as I learn
        BoxView silverBoxView = new BoxView
        {
            Color = Colors.Silver,
        };
        DrawingCanvas.Add(silverBoxView);
        r = new Rect(0, 20, 200, 5);
        DrawingCanvas.SetLayoutBounds(silverBoxView, r);

        BoxView brownBoxView = new BoxView
        {
            Color = Colors.Brown,
        };
        DrawingCanvas.Add(brownBoxView);
        r = new Rect(10, 0, 5, 65);
        DrawingCanvas.SetLayoutBounds(brownBoxView, r);

        BoxView greenBoxView = new BoxView
        {
            Color = Colors.Green,
        };
        DrawingCanvas.Add(greenBoxView);
        r = new Rect(20, 0, 5, 65);
        DrawingCanvas.SetLayoutBounds(greenBoxView, r);
        greenBoxView.GestureRecognizers.Add(pointerGestureRecognizer);

        BoxView purpleBox = new BoxView
        {
            Color = Colors.Purple,
        };
        DrawingCanvas.Add(purpleBox);
        r = new Rect(100,100,100,100);
        DrawingCanvas.SetLayoutBounds(purpleBox, r);
        purpleBox.GestureRecognizers.Add(pointerGestureRecognizer);

        Label headerLabel = new Label
        {
            TextColor = Colors.Red,
            Text="Stylish Header Demo",
            FontSize=24,
        };
        DrawingCanvas.Add(headerLabel);
        r = new Rect(30, 25, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize);
        DrawingCanvas.SetLayoutBounds(headerLabel, r);

Page URL
https://learn.microsoft.com/en-us/dotnet/maui/user-interface/layouts/absolutelayout?view=net-maui-8.0
Content source URL
https://github.com/dotnet/docs-maui/blob/main/docs/user-interface/layouts/absolutelayout.md
Document Version Independent Id
d8aac004-9823-8211-3e9d-aefe7d9c4d95
Article author
@davidbritch
Metadata

ID: d8aac004-9823-8211-3e9d-aefe7d9c4d95
Service: dotnet-mobile
Sub-service: dotnet-maui

Hi @Tandry
If you read the paragraph after the code example you've cited, you'll read: "The C# example uses the following Add extension methods to add children to the AbsoluteLayout:" followed by the extension methods you require. Then the code will work.

I provided working code.  .Add does not take two arguments:  CS1501: No overload for method 'Add' takes 2 arguments.
The corrected code replaces
       absoluteLayout.Add(new BoxView
        {
            Color = Colors.Silver
        }, new Rect(0, 10, 200, 5));

with
BoxView bv = new BoxView { Color = Colors.Silver };
absoluteLayout.Add(bv);
Canvas.SetLayoutBounds(bv, new Rect(0, 10, 200, 5));

HI @Tandry
Yes, I get that your code works. But the code in the doc also works, via an Add extension method that does take two arguments. The Add extension method is in the doc, and in the sample the doc links to.

David,
Let's consider the use case of someone new to MAUI who is unfamiliar with its internal workings.  That person, my earlier self in this case, is going to expect Microsoft's code to compile as provided.  It would be one thing to say, "Here's some code that does the trick - but be aware that it needs this extension in order to work." and THEN provide the code, but that warning is not up front.  Instead, the documentation states, "The equivalent C# code is shown below" and a block of code is provided with a copy button.  It's natural for that newbie to assume that code works without further reading or inclusion of subsequent blocks of code.
I highly recommend that the documentation support the use case which comes naturally to this user, without modifying or extending "stock" methods on standard objects.  What if, for whatever reason, I don't wish to extend .Add()?  For one thing, for fear of ripple effects or repercussions down the road since that person is brand new and clueless as to what ripple effects those may be.
A best practice here is to provide code that, without extending the objects or adding any functionality - especially completely unnecessary extensions - does the trick.  Alas, the simpler example is present - it's in the proportional example near the bottom of the documentation but even that is not called out as different - we get the same "The equivalent C# code is shown below".
Speaking only for my own case, I was not interested in proportional layouts, so I did not look at that example.  I was interested in "absolute" and my reasonable expectation was that I could tap that "copy" button so conveniently provided and paste the code into my work, make the needed changes to variable names and...oh..crap...this doesn't compile.   This left me to pursue a 2 to 3 hour goose chase through dozens of seemingly applicable but half-decade old Xamarin questions in StackOverflow.  If only I could bill Microsoft for my wasted time!
Documentation needs to serve the customer and the customer's use case here is to learn MAUI.  The flow of that documentation can strongly affect the customer's frustration level (don't get me started on the reams of pages which are supposed to "document" feature X and all they do is say, "Feature X provides functionality X" - without ever saying what the (&#%(&#% the bloody thing is intended to be used for!  This is a struggle I gave up on during my 8 years as a blue badge FTE at Microsoft.  But I digress.
As a new learner, I would highly recommend providing the simplest, guaranteed to work solution first, without embellishment and the litmus test for that is "does the copy button provide the ability to splice this code into VS and guarantee working functionality without alterations beyond basic variable name alignment".  I've been writing in C# for decades, so lack of knowledge of the language is not the problem.
Once a student understands what's needed - in this case, create the Control, Add the Control to the Layout and THEN set the position - in that order - THEN they can understand how to bend the rules.  It turns out that in my case, the presented solution with the extension was not viable either because I'm adding a PointerGestureRecognizer to the BoxView, so I need to capture the return from that constructor.  So again, the simple solution is the only one that worked in the long run.
I dearly hope that the team decides to align the documentation around reasonable and expected use cases by those who are clueless enough (such as my earlier self) to need to go to the documentation in the first place.
Cheers,
Steve


Default Dimensions for Extension Table

Hi,
I was trying to add Default Dimensions to a Master Data Table from my Extension.
So I added the "Dimension - Single" action to my Page according to the pattern used in e.g. Customer List.
No problem to depoy it, but unfortunately the "Default Dimension" table has a Table Relation, which is also validated.
IF (Table ID=CONST(13)) Salesperson/Purchaser ELSE IF (Table ID=CONST(15)) "G/L Account" ELSE IF (Table ID=CONST(18)) Customer ELSE IF (Table ID=CONST(23)) Vendor ELSE IF (Table ID=CONST(27)) Item ELSE IF (Table ID=CONST(152)) "Resource Group" ELSE IF (Table ID=CONST(156)) Resource ELSE IF (Table ID=CONST(167)) Job ELSE IF (Table ID=CONST(270)) "Bank Account" ELSE IF (Table ID=CONST(413)) "IC Partner" ELSE IF (Table ID=CONST(5071)) Campaign ELSE IF (Table ID=CONST(5200)) Employee ELSE IF (Table ID=CONST(5600)) "Fixed Asset" ELSE IF (Table ID=CONST(5628)) Insurance ELSE IF (Table ID=CONST(5903)) "Service Order Type" ELSE IF (Table ID=CONST(5904)) "Service Item Group" ELSE IF (Table ID=CONST(5940)) "Service Item" ELSE IF (Table ID=CONST(5714)) "Responsibility Center" ELSE IF (Table ID=CONST(5800)) "Item Charge" ELSE IF (Table ID=CONST(99000754)) "Work Center" ELSE IF (Table ID=CONST(5105)) "Customer Template" ELSE IF (Table ID=CONST(849)) "Cash Flow Manual Revenue" ELSE IF (Table ID=CONST(850)) "Cash Flow Manual Expense"
Any idea, how I can solve that? Does it actually make sense to have the Table Relation here?

Unfortunately you cannot extend dynamic table relations yet. It is on our backlog, but hasn't been been picked up yet. I will add a +1 request from you :-)

Please add a +1 request for me to.

Please describe scenario for this - the user can set the default Dimensions within Business Central - in which scenarios is it needed to set this from an Extension.

Our ISV solution is in the automotive retail space. Therefor we are dealing with Vehciles.
When selling something to a Customer (A Sparepart or a Service), it is often required to select for which specific Vehicle that Sale is done. You select the Vehicle in the Document Header.
So we have the additional Vehicle Master Entity and would like to be able to derive Dimensions from the selection based on the standard Default Dimension Concept.

Thank you - got it, we will investigate possible solutions to this.

Here is the solution we came up with:
The table relation is blanked and replaced by the code in trigger "No.".OnValidate() that verifies if the record with primary key equal to "No." in the table set in "Table ID" field.
The removed table relation had been handling the renaming of the related tables. This is now implemented by the call of function COD408.RenameDefaultDim() in the trigger OnRename() of all related tables.
Extensibility:
"Table ID" in table 352 is verified against the list of table IDs returned by COD408.DefaultDimObjectNoList().
This function collects all tables that match the following conditions:

have fields related to global dimensions
do not have "Dimension Set ID" field
their primary key include one field

If the extension table satisfies these conditions, its ID will be accepted by table 352 automatically.
If the table does not get to the list it can still be added by subscription to the event COD408.OnAfterSetupObjectNoList() and modifying the buffer table.


Fix autoCenter to work for pole

Given the very small diameter of the pole and the narrowness of the distance sensor's beam, the solution for auto-centering on the pole will require centering at a further distance out from the pole and then driving forward a fixed distance.

For the pole we we initiate auto-centering at 20cm and finish centering at 11cm.  At 11cm, the pole should still be clearly "seen" by both distance sensors.  After autoCenterLoop() returns, the autonomous code will need to drive forward 7-8cm prior to opening the grabber to drop the cone.


Convert to meta-package

We are close to being ready to convert Tidier.jl to a meta-package that re-exports TidierData, TidierPlots, TidierCats, TidierStrings, and TidierDates.
Here is the checklist of things we need to figure out and work on:

[x] Need to fix an issue where TidierCats cannot correctly register its functions as non-vectorized within the separately loaded TidierData package. This is a complex issue that involves fixing both TidierData and TidierCats, but I think I am close to having a solution.

[x] Remove almost the entire package except for the main page, which re-exports all the base packages with compatability noted as >= designation for version numbers of underlying packages.

[x] Redo README and docs so that they point to the individual packages -- we should add some simple examples to show how the packages work together but remove the current examples so that this isn't simply a replication of the TidierData docs.

Resolved in #115.


.nan in orientation filed of pose topic

Hi
I'm using ROS 2 (Humble on Ubuntu 22.04)  with the septentrio_gnss_driver with mosaic-H and dual antenna setup. In the web gui I can see that a heading and pitch are being correctly reported. However the ROS "pose" topic contains only ".nan" for the "orientation" field.
Are you able to help please?

Hi @mirons5678,
your observation is correct. For the GNSS receivers, the orientation is set to .nan on purpose. This is because only an INS is able to determine full orientation. For a dual-antenna GNSS it depends on the antenna setup which tilt angle can be observed. In case the heading offset is not a multiple of 90 °, it is neither roll nor pitch. Maybe we can think of outputting only heading?

Hi @mirons5678 ,
thank you for your report. The calculation for the GNSS contained an error, since it can only determine either roll or pitch and the other is .nan. I have a quick fix here and the fix will be part of the next update. Because this is valid just for a heading offset of  a multiple of 90 °, pitch and roll have to be used with care. Only an INS is able to determine full orientation.

Thanks for the quick reply @thomasemter. I was hoping to fuse heading from the GNSS into a robot localization EKF node, which I think requires a Pose message with orientation - I'm using a heading offset of 90°. Should your fix enable me to do this? Do you have any idea when the next update will be released?

Heading can be used for sure. If you are referring to robot_localization it is easily possible to exclude pitch and roll.
I hope the next update will be released very soon.

Thanks for your support @thomasemter . With your updated branch I'm seeing orientation data in the Pose message. I'm fusing this into robot_localization and only including yaw from the GNSS pose topic. This is fused with x and y velocity from a wheel odometry topic. However, when the x and y velocity are 0, the yaw angle is continually rotating through 360° (even when the antenna are static and the web interface is showing an accurate heading). Do you have any idea why this might be?
I've also observed that setting att_offset: heading in the GNSS driver config file does not appear to be honoured (e.g. setting att_offset: heading: 90.0 shows as a heading offset of 0.0 in the web GUI).

Great to hear. I am sorry, but I am not very familiar with robot_localization since we use our own fusion framework at our institute.
In my setup, the heading in the WebUI reflects the parameter setting.

If you have set get_spatial_config_from_tf: true, the heading offset is drawn from tf and setting att_offset.heading has no effect. Also, if you have set use_ros_axis_orientation: true, the sign of the heading offset will be reversed since it follows a different convention.


Running build:prod gives an internal aurelia-templating-resources error

When running the task:
npm run build:prod
The following error is displayed:
ERROR in app.12ac6a8608bb86e5f96e.bundle.js from UglifyJs SyntaxError: Unexpected token: name (length) [app.12ac6a8608bb86e5f96e.bundle.js:4072,6] Child html-webpack-plugin for "index.html":         + 4 hidden modules Child extract-text-webpack-plugin:         + 2 hidden modules
Any ideas what this could be, tracking down the bundle js it appears to be triggered from this line of aurelia-templating-resources:
`function updateOverrideContexts(views, startIndex) {
let length = views.length;
if (startIndex > 0) {
startIndex = startIndex - 1;
}
for (; startIndex < length; ++startIndex) {
updateOverrideContext(views[startIndex].overrideContext, startIndex, length);
}`
Any help would be appreciated! Thanks

Seems like the error is coming from Uglify. Any ideas why Uglify might not like length from the above snipped?

Yeh, removing Uglify removes the error, a bit of searching points to incompatibilities with Uglify and ES6 syntax ...

Uglify shouldn't be receiving any ES6 though. All of Aurelia is compiled to ES5.

Everything is compiled to es65 in the output, except everything after the aurelia-templating-resources code above - that seems to be verbatim ... weird!

don't you have a moduleOverrideRoot in your package json by any chance, pointing to the es2015 directory of templating-resources?

Yeh I do indeed - punting that from previous version fixed it - thanks!


DEV: FsR: Mappings

EPIC:
#491 Fluids Report Implementation
PARENT:
#493 Add to Store (C) Fluids Report Object
SIZE:
4 hours = 1/2 day = 1 point (confirm size with TS)
Development for Mapping  for ADD to Store

UPDATE: The converter with the mappings has been completed after review by Chris. There will not be an extended converter, so the following is true:
<IP_ADDRESS> -> 2.0, 2.0 -> <IP_ADDRESS> is done
<IP_ADDRESS> -> 2.0, 2.0 -> <IP_ADDRESS> is done
no effort for 2.0 -> 2.0 is required (obvious but worth mentioning)

Update: There was some missing data that has now been provided by the Mapping software. To my knowledge, all required elements are there so I am closing this card.


Migrate from TravisCI to GitHub Actions

This is needed to be able to merge any pull requests, as the tests are not being run currently.

Hey, @mr-c I can do this! Can you please assign this one to me?

@Anushka-shukla Done!

Hey, @mr-c I've opened this draft PR can you please provide feedback on this?


Refresh on a show is not working

Hi...
Verified against PMS running on NVIDIA Shield:
odaat = plex.library.section('Serien Deutsch').get('One Day at a Time (2017)')
odaat.refresh()

gives
Traceback (most recent call last):
  File "C:\Temp\PlexLister.py", line 30, in <module>
    odaat.refresh()
  File "C:\Program Files (x86)\Python35-32\lib\site-packages\plexapi\video.py", line 164, in refresh
    self.server.query('/library/metadata/%s/refresh' % self.ratingKey)
  File "C:\Program Files (x86)\Python35-32\lib\site-packages\plexapi\server.py", line 110, in query
    raise BadRequest('(%s) %s' % (response.status_code, codename))
plexapi.exceptions.BadRequest: (405) method_not_allowed

Thanks.

got the solution from plex forums: https://forums.plex.tv/discussion/comment/1353252
it has to be a PUT not a GET to work!
verified with CURL:
C:\Temp>curl -k -X PUT https://xxxx:32400/library/metadata/135268/refresh?X-Plex-Token=xxxxxxx
<?xml version="1.0" encoding="UTF-8"?>
<MediaContainer size="0" identifier="com.plexapp.plugins.library" mediaTagPrefix="/system/bundle/media/flags/" mediaTagVersion="1482655637">
</MediaContainer>

This is has been fixed in my reponses branch.

Responses branch merged and a test for this function is added and passing: test_video_Show_refresh
commit 6e761f0fc5bf026e5ef980a884f8e9e0f3a8af09
Merge: 5f9c230 e2efc5f
Author: Michael Shepanski<EMAIL_ADDRESS>Date:   Wed Feb 1 22:05:59 2017 -0500
Merge pull request #100 from Hellowlol/responses
Responses


main.js

https://github.com/mobilekosmos/demo-apps/blob/main/moralis-sign-in-boilerplate/main.js

unclear, closing


RatInABox custom Gym environment for RL

Hi,
Your repo is really cool and the visuals are excellent. However, when going through the RL example section, I find that although the example is decent, it still leaves a lot of the skeleton showing (in terms of all the direct stuff you do with the environment and the agent). I would really like to give PPO with an intrinsic curiosity module a go, since your environment is quite interesting. Specifically, to see what the rat would do if only rewarded with curiosity vs the environment reward and curiosity. It would be also be interesting to see if it has rat-like exploration and what would happen if the reward was as sparse as possible (e.g a reward for only reaching the reward square).
However, it feels a bit difficult to interact with it and get something like that working immediately. Mainly because the environment is not making use (at least in this case https://github.com/TomGeorge1234/RatInABox/blob/1.x/demos/reinforcement_learning_example.ipynb) of the standard Markov Decision Process abstraction. If you had this abstraction, I think it would be super cool since it makes it much easier to try out a variety of RL methods quickly and easily on the task, as it cleanly separates the RL part and your environment.
Not sure if this is a useful suggestion, but if it is I would be super keen to interact with the environment if it has this modification given how cool and interesting your repo looks.

... slightly more functional fork now:
https://github.com/SynapticSage/RatInABox/blob/task_environments/ratinabox/contribs/TaskEnvironment.py

Nice! I'm very impressed, just took a look and it seems really nice so I'm excited to have a play around. At some point perhaps would be great to PR this into the main branch but I'll leave some comments once I've taken a look and leave this thread open in the meantime.
Appreciate the legwork !

Awesome. Ya comments would be appreciated.  Not mature enough for a PR. Maybe eventually.
Top priority---my guess--would be figuring out how the agent should interface and register a controller for its actions to its member environment. Gymnasium environments store an observation space and an action space as attributes. And the action_space attribute can be a list/dict of action spaces for the registered agents who belong to the task.
But the main rub is that action spaces themselves, I imagine, could be based on different things. E.g. drift_velocity in your script. And then there's something upstream of the controller pulling the strings of the controller, e.g. an agent/neuron. And may need some brainstorming on how to organize interfacing up a given action_space to a agent's controller to variables within {agents, neurons, other-things}.

Yeah, I think I see. To me it seems quite natural that the state space should be a concatenation of the current firing rates of a list of RatInABox Neurons. So if the Agent has some PlaceCells and GridCells its state is entirely determined by the firing rates of those two populations (and nothing else). The action space should be, as you say, drift_velocity (and perhaps the ratio parameter determining drift-to-random motion proportions, since this is kind of close to $\epsilon$ in $\epsilon$-greedy it may be more of a hyperparameter).
Happy to jump on a call some time if it would help, keen to get this off the ground and I'm aware of other people who would use this functionality!

For sure -- think I'm on the same page. Makes total sense neurons should provide the input for the action space for obvious reasons---and the focus of your package. Was only probing if there was an appetite for knobs for other moments of inertia or general input from other objects.
Pushed some updates. There's an action space (assuming drift_velocity knobs) for each agent, reward, and a loop invoking Gymnasium's step() paradigm.

Really like where this is going. I ran the code, it works great! Some thoughts:

Continuous time : We should make the time continuous so on each update() there are two updates: self.time += self.dt (defaulting to say 0.01) and self.steps += 1. The spirit of RiaB is very much to treat time and space continuous...a departure from classic RL where time is a more abstract thing.
Handy RiaB geometry funcs There's a useful (if poorly named) function called Env.get_distance_between___accounting_for_environment(pos1, pos2,wall_geometry="line_of_sight")...this does as it says on the tin and will return very large number if there is a wall obstructing the straight line path between pos1 and pos2. This will be necessary in the future to leverage full flexibility of RiaB environments with complex wall structures.
Aesthetics Is it possible to maintain consistency with RiaB plotting functions? i.e. use Agent.plot_trajectory(). I'm suspecting maybe this wouldn't be easy as you are doing this efficiently by resetting (rather than replotting) the data each time, nice work btw. I wouldn't die on this hill but I would like to maintain aesthetic consistency where possible. It might help if I restructured how plotting works and wrote a function which returns a matplotlib LineCollection. Lmk.
Multiple Agents I really like that you can have multiple Agents. I'm aware this is probably a faff for you to handle but please keep going with it! By the way, wouldn't this be better handled by petting zoo (I'm no expert here!). Also has gym been replaced with gymnasium - if so we should switch for future-proofing.
1D On the other hand, very happy for you to let go of maintaining functionality in 1D Environments, at least for now. :)))
Action space
Lastly in terms of the action space. I sort of agree with your pseudo code above ^ except it should be more general. Whilst it could be something like SomeNeurons.drift_velocity()...in theory it could be something more complex e.g. actor-critic SomeActorTrainedBySomeOtherPackageInterfacingWithThisGym.drift_velocity() or PPO or Q-learning whatever ! The example I gave of linear ValueFunction ascent is pretty basic and ultimately quite limiting.

Continous time and geometry funcs: Great suggestion! I hadn't considered these yet. I have now implemented the changes.

Aesthetics : This might be feasible. render() already calls environment's plot and could call those plots first to initialize the line collections. I'll see if it's quick to implement.

Further down the line, you might however consider having each object (environment, agent) be responsible for implementing its own render(), ie cache its own plot objects. It's potentially strange having a task environment cache plot objects about non-task environment features?
If so, I imagine instead a scheme where someone calls the environment'senv.render() after env.step. Whereon, inside the environment's render(), env would call render() on any object that contains which implements its own render, and so on... render()ing down a cascade of objects. More concretely here, render() would call Agent.render() and Objective.render(). And then those objects could in turn survey for any objects they have with render()and call those. Maybe even in some cases neurons attached to agents have a render() method turned on to plot inside the env.step(); env.render() loop.

Multiple agents: To me I was imagining someone will eventually want to study social vector cells or social tasks at some point; maybe RiAB could help with that. Not tricky to allow---basically just an extra loop.

gym/gynasium: I'm behind the  times. I learned how to use gym in 2019. Didn't know that openai moved its functionality to gymnasium. Seems to keep the same interface as far I can tell. Good points. Wouldn't want the objects calling deprecated code.

Same story for petting zoo: it arrived after my last brush with the API, to my knowledge.

Reward: Great ideas! The reward pulses were just a quick n' dirty implementation win. Will check it out.

Action space: 🙂 Had meant as more of an example as opposed to prescription. Aware.

Ok, I will definitely consider restructuring some of the plotting stuff (seems like each Agent and Environment classes could have an internal _render() function which plots everything it needs to and returns all matplotlib plot object. The plot_trajectory() or whatever function would then just set the data on all these objects. Its a medium sized change however and not essential so for now lets presume to work around it.
Maybe worth looking into petting zoo. I don't know if it would streamline the multiagent stuff, presumably they built it for a reason 🤷🏼♂
Nice progress though! keep me updated how things get on, looking forward to having it complete!

Excellent. Ya, no rush on the _render(). It's fine without it.
Pushed some changes aligning the code with pettingzoo yesterday

step works as expected for the multi-agent case.
It's potentially annoying to work with dicts of actions per agent for single-agent environments, so added a step1() wrapper function that makes the task environment behave like gymnasium. step1 is short for "step with 1 agent". Cuts all the boilerplate and fluff associated with mutli-agent---if people are into that.

Generalizing the reward structure next: Provisioned some structure for it. Plan is to attach one cache object containing an agent's active rewards to the environment and put a reference to that same cache inside the agents. That way rewards can be triggered externally from the environment or internally from the neurons that are part of the agent.

Posted an update with non-sparse rewards. Have a few features that decide a reward's dynamics:

initial value
decay rate for the reward from the initial value (linear, constant, exponential)
follower term that can be used to attach a ramping signal or goal gradient to a reward
expiration time: how long does the reward stay active from the moment it appears. None means that the reward never expires, but follows its gradient and decay dynamics.

Awesome!! Happy to see such rapid progress progress being made. Thanks for upgrading to pettingzoo, I see what you mean about it being a bit annoying for single agents but your solution seems good. And also thanks for updating the plotting stuff, really nice :))
I like the reward flexibility here - both being able to have multiple rewards and agent or environment dependent rewards. Seems sensible that rewards can be environment, not agent, specific in the cases that multiple agents are competing for the same external rewards. It's also really nice how the rewards can be set on each trial and are stored in a growing cache and expire after a set amount of time.
Could you please clarify to me the difference/connection between Objectives and Rewards. I'm a tiny bit confused about the causality here. Objectives just determine the conditions for ending a trial but are they linked to the rewards? As I understand it, each time an Environment is reset new goal positions are sample each defining a spatial Objective. Does this then trigger the creation of a Reward object which gets added to the cache?

Ya, no worries. Happy to clarify! Not particularly married to this scheme if its awkward.
The Objective represents a specific task rule or condition that must be fulfilled to solve the task. When an agent meets an Objective, the Objective may optionally release a Reward object. A task episode consists of a list of Objective, and the episode ends when all Objectives are completed. In this way, Objectives represent a collective terminal state.
Now, a task environment would allow having one without the other: you could create a rule without a reward or create a reward without a rule. In other words, a user constructing a task could choose to release elicit Reward/(punishment) without an Objective or vice-versa. An objective is, if anything, just an organizing class to build a task rule. I imagine if people contribute different tasks (as they do neurons) to RiAB, objectives from different tasks could be mixed and matched to make new tasks.
When an environment reset()s, the env replenishes a list of Objective from a pool of potential objectives for a task episode. This is controlled by how users design the reset() for their task; it could be as random or deterministic the task maker would like.
If it's too tricky---totally fine if someone wants to lump Reward/Objective into a single object. Slightly more configurable and amenable to polymorphism as separate objects, but I could see there being more boilerplate and cognitive load on the programmer to remember.

Commit from earlier this week.
`Objective` and `Goal` have similar semantic feelings ---a
potential source of confusion. Additionally, `Objective` could
be wrongfully confused by the user as the objective function of
some RL or otherwise algorithm running the agents. Hence, I
refactored everything clarify; `Objective` has been changed to
`Goal`, which cleans up semantics.

----------
New object
----------

Similar to how `RewardCache` tracks a collection of rewards,
`GoalCache` now tracks a collection of goals. In particular,
how one or many agents can interact with them. Some things it
can handle for the user:
- do goals have to be completed in sequence? or does order
  not matter?
- Does each agent have to finish a given goal? Or is it
  consumed by another agent?

`GoalCache` is basically a fancy goal list that handles
tracking how agents satisfy goals under those differing
schemata.

Still a few bugs to be ironed out. Hoping that object relations read/feel a little more intuitive and clean now.

Very happy with this. It makes sense that rewards and objectives (now goals) should be disentangled as in reality they needn't be one-to-one. At the end of the day some kind of demo and readme/doc will be necessary to explain all this to end users (as it isn't. trivial) but we can cross that bridge when we come to it. The flexibility you've coded into this will pay off in the long run; as it stands (once bug etc. are ironed out) this could account for so many spatial behaviour set-ups, very impressed.
I thought I'd share this here so others can see the progress made so far:
https://user-images.githubusercontent.com/41446693/231140004-9a408a29-0a7c-4801-82a8-b8e68c0cb02e.mov

Totally agree that the TaskEnvironment, Goal, and Reward objects might not be trivial for users to quickly grasp. Creating a markdown document doc file with illustrations will make it much easier to comprehend---learning tools from comment headers can be challenging.
Currently, there are some bugs and untested features:

goalorder = sequence (bug)
agentmode = noninteracting (untested)
a couple reward-related options (untested)

Busy lab week ri now; I will try to address these on Friday/Saturday, possibly set some pytests. After which, I imagine it might be ready to document and PR into RiAB.
Awesome---glad that things are coming together.

Bugs ironed out. Maybe best to transition to documentation/PR soon.

Brilliant! Feel free to PR when you feel it's ready. As this is a standalone script the requirements for inclusion aren't too high and we can carry on ironing out bugs once it's live.

Hi @SynapticSage how is this coming along? Reckon it will be ready for a PR some time soon?

Apologies for the delay. Hectic month; PR fell off my radar.
I'll submit it this weekend. Code is operational, but the tutorial needs a little more info here and there. I'll be continuing to refine it after the PR -- as suggested.
Thanks for your patience!

No worries, was just checking everything was fine. Definitely happy for you to continue to refine it afterwards, much better that way

Closing as this has now been pushed to contribs. Thanks!

Hi Ryan! I would like to make a SpatialGoalEnvironment where there is a short delay after completing the spatial goal before the episode terminates, this is to allow the Agent to experience the temporally extended reward - otherwise I'm concerned that the reward will be experienced in the following episode (where, here, I'm teleporting the agent to a new location) and credit misattributed. What's the best way to do this?

Just shot over a PR for this. Nice QOL improvements: do think the code formatting could use standards.
So sans the PR, one could just add an unrewarded timer() goal at the end of the goal sequence.
But since this is a super common need (e.g. for ISIs), just added a shortcut TaskEnvironment attribute delay_episode_terminate. It's more or less accomplished by padding an unrewarded timer goal when agents finish their episode goals.

The side question:
Yes, unfortunately. It's a pettingzoo attribute. pettingzoo expects this variable to track the active agents (those who are still able to receive actions during the episode). I wasn't originally planning to have that, but had to add it to appease the pettingzoo environment tests.

Absolutely! env.t. Totally my mistake. Was distracted while I was typing that part out.
Regarding the reward, you can also give it a None object instead of no_reward_default, but maybe it's nice to be explicit.

Oh, a None object is way cleaner I prefer that.

Sounds good. Goal setting a link to itself in the reward was a relatively recent change. Must have broken the None option.
Will try to resurrect it next PR.


Update angular-cli monorepo to v15 (major)

This PR contains the following updates:

Package
Type
Update
Change

@angular-devkit/build-angular
dependencies
major
14.2.7 -> 15.1.3

@angular/cli
dependencies
major
14.2.7 -> 15.1.3

Release Notes

angular/angular-cli
v15.1.3
Compare Source
@angular/cli

Commit
Type
Description

de15ec576
fix
handle extended schematics when retrieving aliases

@schematics/angular

Commit
Type
Description

2c04f4a8f
fix
update browserslist config to include last 2 Chrome version

@angular-devkit/build-angular

Commit
Type
Description

f31bf300b
fix
avoid undefined module path for Sass imports in esbuild

c152a4a13
fix
update browserslist config to include last 2 Chrome versions

@angular-devkit/core

Commit
Type
Description

9de99202e
fix
handle number like strings in workspace writer

Special Thanks
Alan Agius, Charles Lyding and Doug Parker

v15.1.2
Compare Source
@angular/cli

Commit
Type
Description

387472a95
fix
register schematic aliases when providing collection name in ng generate

5d9fd788a
fix
remove --to option from being required when using --from in ng update

@schematics/angular

Commit
Type
Description

0f5fb7e59
fix
replace existing BrowserModule.withServerTransition calls when running universal schematic

@angular-devkit/build-angular

Commit
Type
Description

bf4639a6e
fix
prevent hanging initial build during exception with esbuild

Special Thanks
Alan Agius, Charles Lyding and Doug Parker

v15.1.1
Compare Source
@angular-devkit/build-angular

Commit
Type
Description

b94bf60ca
fix
update esbuild to 0.16.17

Special Thanks
Alan Agius

v15.1.0
Compare Source
Deprecations
@angular-devkit/schematics

The Observable based SchematicTestRunner.runSchematicAsync and SchematicTestRunner.runExternalSchematicAsync method have been deprecated in favor of the Promise based SchematicTestRunner.runSchematic and SchematicTestRunner.runExternalSchematic.

@schematics/angular

Commit
Type
Description

5b18ce154
feat
add guardType as an alias of implements in guard schematic

dd2b65943
feat
add configuration files generation schematic

8d000d156
feat
add environments generation schematic

6c39a162b
feat
Add schematics for generating functional router guards and resolvers

62121f89a
feat
add sideEffects:false to library package.json

9299dea64
feat
generate functional interceptors

49b313f27
fix
add missing import for functional interceptor spec

2f92fe7e5
fix
add missing semicolon in functional guard/resolver/interceptor

9b6d190f4
fix
remove EnvironmentInjector import in functional guard spec

b11d3f644
fix
use proper variable in functional guard spec

451975f76
fix
use proper variable in resolver functional spec

@angular-devkit/build-angular

Commit
Type
Description

c29df6954
feat
add assets option to server builder

839d0cb57
feat
implement stats-json option for esbuild builder

216991b9d
feat
support inline component Sass styles with esbuild builder

7c87ce47c
fix
ensure Sass load paths are resolved from workspace root

7a063238b
fix
explicitly send options to JS transformer workers

22cba7937
fix
provide an option to exclude specs in Karma builder

20376649c
fix
transform async generator class methods for Zone.js support

0520608f6
fix
use relative css resource paths in esbuild JSON stats

0c01532cb
perf
use worker pool for JavaScript transforms in esbuild builder

@angular-devkit/schematics

Commit
Type
Description

207358afb
feat
add runSchematic and runExternalSchematic methods

Special Thanks
Alan Agius, Andrew Scott, Charles Lyding, Cédric Exbrayat, Doug Parker, Felix Hamann, Jason Bedard, Joey Perrott and Kristiyan Kostadinov

v15.0.5
Compare Source
@angular-devkit/build-angular

Commit
Type
Description

c2030dec7
fix
format esbuild error messages to include more information

Special Thanks
Alan Agius, Kristiyan Kostadinov, Paul Gschwendtner and aanchal

v15.0.4
Compare Source
@angular-devkit/build-angular

Commit
Type
Description

ccc8e0350
fix
display actionable error when a style does not exist in Karma builder

507f756c3
fix
downlevel class private methods when targeting Safari <=v15

a0da91dba
fix
include sources in generated

9fd356234
fix
only set ngDevMode when script optimizations are enabled

8e85f4728
fix
update css-loader to 6.7.3

b2d4415ca
fix
update locale setting snippet to use globalThis.

Special Thanks
Alan Agius and Charles Lyding

v15.0.3
Compare Source
@angular-devkit/build-angular

Commit
Type
Description

3d9971edb
fix
default preserve symlinks to Node.js value for esbuild

24f4b51d2
fix
downlevel class fields with Safari <= v15 for esbuild

45afc42db
fix
downlevel class properties when targeting Safari <=v15

e6461badf
fix
prevent optimization adding unsupported ECMASCript features

Special Thanks
Charles Lyding, Dominic Elm and Paul Gschwendtner

v15.0.2
Compare Source
@angular-devkit/build-angular

Commit
Type
Description

2891d5bc9
fix
correctly set Sass quietDeps and verbose options

@ngtools/webpack

Commit
Type
Description

d9cc4b028
fix
elide unused type references

Special Thanks
Alan Agius and Juuso Valkeejärvi

v15.0.1
Compare Source
@angular/cli

Commit
Type
Description

eda96def4
fix
use global version of the CLI when running ng new

@schematics/angular

Commit
Type
Description

48426852b
fix
show warning when a TS Config is not found during migrations

@angular-devkit/build-angular

Commit
Type
Description

2af32fd3a
fix
hide loader paths in webpack warnings

19f5cc746
fix
improve package deep import Sass index resolution in esbuild plugin

2220a907d
fix
use url function lexer to rebase Sass URLs

Special Thanks
Alan Agius, Charles Lyding, Doug Parker, Joey Perrott and Piotr Wysocki

v15.0.0
Compare Source
Breaking Changes
@angular/cli

The Angular CLI no longer supports 16.10.x, 16.11.x and 16.12.x. Current minimum versions of Node.js are 14.20.0, 16.13.0 and 18.10.0.
Node.js versions older than 14.20 are no longer supported.
The 'path' option in schematics schema no longer has a special meaning. Use 'workingDirectory' smart default provider should be used instead.

@schematics/angular

Removed unused appDir option from Universal and App-Shell schematic. This option can safely be removed if present since it no longer has effect.

analyticsSharing option in the global angular configuration has been
removed without replacement. This option was used to configure the Angular CLI to access to your own users' CLI usage data.
If this option is used, it can be removed using ng config --global cli.analyticsSharing undefined.

analytics APIs have been removed without replacement from @angular-devkit/core and @angular-devkit/architect.

@angular-devkit/build-angular

TypeScript versions older than 4.8.2 are no longer supported.

The server builder bundleDependencies option has been removed. This option was used pre Ivy. Currently, using this option is unlikely to produce working server bundles.
The externalDependencies option can be used instead to exclude specific node_module packages from the final bundle.

Deprecated support for tilde import has been removed. Please update the imports by removing the ~.

Before
@import '~font-awesome/scss/font-awesome';

After
@import 'font-awesome/scss/font-awesome';

By default the CLI will use Sass modern API, While not recommended, users can still opt to use legacy API by setting NG_BUILD_LEGACY_SASS=1.

Internally the Angular CLI now always set the TypeScript target to ES2022 and useDefineForClassFields to false unless the target is set to ES2022 or later in the TypeScript configuration. To control ECMA version and features use the Browerslist configuration.

require.context are no longer parsed. Webpack specific features are not supported nor guaranteed to work in the future.

Producing ES5 output is no longer possible. This was needed for Internet Explorer which is no longer supported. All browsers that Angular supports work with ES2015+

server builder bundleDependencies option now only accept a boolean value.

Deprecated support for Stylus has been removed. The Stylus package has never reached a stable version and its usage in the Angular CLI is minimal. It's recommended to migrate to another CSS preprocessor that the Angular CLI supports.

@angular-devkit/core

Workspace projects with missing root is now an error.

@ngtools/webpack

TypeScript versions older than 4.8.2 are no longer supported.

@schematics/angular

Commit
Type
Description

766d4a089
feat
add migration to remove require calls from karma builder main file

d8bff4f1e
feat
Added --project-root option to the library schematics

597bfea1b
feat
drop polyfills.ts file from new templates

1c21e470c
feat
enable error on unknown properties and elements in tests

f2a0682dc
feat
generate new projects using TypeScript 4.8.2

b06421d15
feat
mark projectRoot as non hidden option in application schematic

b6897dbb0
feat
remove karma.conf.js from newly generated projects

301b5669a
feat
remove ngOnInit from component template

9beb878e2
feat
remove Browserslist configuration files from projects

283b564d1
feat
remove environment files in new applications

56a1e8f9f
feat
remove test.ts file from new projects

4e69e8050
fix
add @angular/localize as type when localize package is installed

57d93fb7d
fix
mark project as required option

84e3f7727
fix
remove empty lines

316a50d75
fix
remove TypeScript target from universal schematic

69b221498
refactor
remove deprecated appDir option

@angular/cli

Commit
Type
Description

4827d1b23
feat
add support for Node.js version 18

4b623461a
feat
drop support for Node.js versions older than 14.20

3dea1fa71
fix
add unique user id as user parameter in GA

af07aa340
fix
add workspace information as part of analytics collection

83524f625
fix
allow ng add to find prerelease versions when CLI is prerelease

22955f245
fix
do not collect analytics when running in non TTY mode

35e5f4278
fix
exclude<EMAIL_ADDRESS>from ng add pa… (#24152)

1a584364e
fix
exclude<EMAIL_ADDRESS>from ng add package discovery

ff0382718
fix
respect registry in RC when running update through yarn

774d349b7
refactor
remove deprecated path handler

Commit
Type
Description

639a3071c
refactor
migrate analytics collector to use GA4

c969152de
refactor
remove analytics API from core and architect

@angular-devkit/build-angular

Commit
Type
Description

4ead45cab
feat
add ng-server-context when using app-shell builder

1c527a9da
feat
add esbuild-based builder initial support for fileReplacements

67324b3e5
feat
add initial incremental code rebuilding to esbuild builder

3d94ca21b
feat
add initial watch support to esbuild-based builder

c592ec584
feat
amend polyfills option in all builders to support an array of module specifiers

a95d130ef
feat
auto include @angular/localize/init when found in types

979bce45e
feat
auto include @angular/platform-server/init during server builds

fd4175357
feat
drop support for TypeScript 4.6 and 4.7

15d3fc6dc
feat
export @angular/platform-server symbols in server bundle

05a98c029
feat
karma builder main option is now optional

2b6029245
feat
providing a karma config is now optional

9c13fce16
feat
remove bundleDependencies from server builder

308e3a017
feat
switch to use Sass modern API

1e5d4a750
feat
use Browserslist to determine ECMA output

3ff391738
fix
account for package.json exports fields with CSS import statements

001445982
fix
account for package.json exports with Sass in esbuild builder

6280741ce
fix
add @angular/platform-server as an optional peer dependency

f9a2c3a12
fix
allow both script and module sourceTypes to be localized

4cb27b803
fix
avoid attempted resolve of external CSS URLs with esbuild builder

192e0e6d7
fix
correct escaping of target warning text in esbuild builder

4fcb0a82b
fix
correctly resolve Sass partial files in node packages

fb5a66ae6
fix
fix crash when Sass error occurs

b6df9c136
fix
handle conditional exports in scripts and styles option

0ee7625d6
fix
ignore cache path when watching with esbuild builder

e34bfe5eb
fix
ignore specs in node_modules when finding specs

f143171fd
fix
only add @angular/platform-server/init when package is installed.

3a1970b76
fix
only import karma when running karma builder

8b84c18ed
fix
provide workaround for V8 object spread performance defect

7dd122ad5
fix
rebase Sass url() values when using esbuild-based builder

2105964af
fix
resolve transitive dependencies in Sass when using Yarn PNP

54e1c01d8
fix
show file replacement in TS missing file error in esbuild builder

6c3f281d9
fix
show warning when using TypeScript target older then ES2022 in esbuild builder

8f8e02c32
fix
support Yarn PNP resolution in modern SASS API

fc82e3bec
fix
update browerslist package

0d62157a3
fix
update sourcemaps when rebasing Sass url() functions in esbuild builder

1518133db
fix
use relative sourcemap source paths for Sass in esbuild builder

fb4ead2ce
fix
wait during file watching to improve multi-save rebuilds for esbuild builder

b059fc735
fix
warn when components styles sourcemaps are not generated when styles optimization is enabled

9d0872fb5
perf
add initial global styles incremental rebuilds with esbuild builder

0fe6b3b75
perf
add vendor chunking to server builder

8c915d414
perf
avoid extra babel file reads in esbuild builder rebuilds

919fe2148
perf
avoid extra TypeScript emits with esbuild rebuilds

92145c4a7
perf
avoid template diagnostics for declaration files in esbuild builder

52db3c000
perf
minimize Angular diagnostics incremental analysis in esbuild-based builder

feb06753d
perf
use esbuild-based builder to directly downlevel for await...of

9d83fb91b
perf
use Sass worker pool for Sass support in esbuild builder

45a94228f
perf
use Uint8Arrays for incremental caching with esbuild-based builder

f393b0928
refactor
disable requireContext parsing

12931ba8c
refactor
remove deprecated ES5 support

7f1017e60
refactor
remove old bundleDependencies enum logic

2ba44a433
refactor
remove support for Stylus

@angular-devkit/core

Commit
Type
Description

ea4c0aa2e
fix
throw error when project has missing root property

de467f46d
fix
update logger forEach promiseCtor type

@angular-devkit/schematics

Commit
Type
Description

9b07b469b
refactor
remove UpdateBuffer and rename UpdateBuffer2 to UpdateBuffer

@ngtools/webpack

Commit
Type
Description

43bd0abc1
feat
drop support for TypeScript 4.6 and 4.7

1c1f985b9
fix
support inline style sourcemaps when using css-loader for component styles

Special Thanks
Alan Agius, Brent Schmidt, Charles Lyding, Cédric Exbrayat, Dariusz Ostolski, Doug Parker, Günhan Gülsoy, Jason Bedard, Lukas Spirig, Ruslan Lekhman, angular-robot[bot] and minijus

v14.2.10
Compare Source
@angular/cli

Commit
Type
Description

9ce386caf
fix
exclude<EMAIL_ADDRESS>from ng add pa… (#24152)

6446091a3
fix
exclude<EMAIL_ADDRESS>from ng add package discovery

7541e04f3
fix
respect registry in RC when running update through yarn

@angular-devkit/build-angular

Commit
Type
Description

21cea0b42
fix
update loader-utils to 3.2.1

Special Thanks
Alan Agius and Charles Lyding

v14.2.9
Compare Source
@angular-devkit/architect

Commit
Type
Description

e3e787767
fix
default to failure if no builder result is provided

@angular-devkit/build-angular

Commit
Type
Description

12b2dc5a2
fix
isolate zone.js usage when rendering server bundles

Special Thanks
Alan Agius and Charles Lyding

v14.2.8
Compare Source
@schematics/angular

Commit
Type
Description

4b0ee8ad1
fix
guard schematics should include all guards (CanMatch)

Special Thanks
Andrew Scott

Configuration
📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about these updates again.

[ ] If you want to rebase/retry this PR, click this checkbox.

This PR has been generated by Renovate Bot.

Renovate Ignore Notification
As this PR has been closed unmerged, Renovate will ignore this upgrade and you will not receive PRs for any future 15.x releases. However, if you upgrade to 15.x manually then Renovate will reenable minor and patch updates automatically.
If this PR was closed by mistake or you changed your mind, you can simply rename this PR and you will soon get a fresh replacement PR opened.