Reflected attributes - lit-element

What's the purpose and use of passing an (internal) property change to an (external) observed attribute? Please, if possible, give an extrovert example.
Tia

One primary use case is that the attribute can then be used by CSS attribute selectors. This way you can easily do conditional styling based on a state:
:host([selected]) .foo {
background-color: gray;
}
:host([mode="foo"]) .bar {
}
Another use case can be reflecting a property to an aria attribute, interpreted by screen readers:
static get properties() {
return {
checked: {
type: Boolean,
attribute: 'aria-checked',
reflect: true,
}
};
}

Related

How to access custom cms element config values in Shopware 6?

FYI: Products is my cms element name.
As shown in shopware 6 guides, I have created a file
DataResolver/ProductsCmsElementResolver.php
which has an enrich method which helps to extend data. In there I try to access the configs of my custom cms element with:
$config = $slot->getFieldConfig();
$productListType = $config->get('products')->getValue();
That, however always returns the default value that was set during the registration of the element:
Shopware.Service('cmsService').registerCmsElement({
name: 'products',
label: 'das.elements.customProductsElement.label',
component: 'sw-cms-el-products',
configComponent: 'sw-cms-el-config-products',
previewComponent: 'sw-cms-el-preview-products',
defaultConfig: {
products: {
source: 'static',
value: ''
}
}
});
I did it exactly as it is shown in the following guides:
https://developer.shopware.com/docs/guides/plugins/plugins/content/cms/add-cms-element
https://developer.shopware.com/docs/guides/plugins/plugins/content/cms/add-data-to-cms-elements#create-a-data-resolver
Could anyone share a sample of code where you get the value of config as a variable and not static value?
What I was doing wrong was that I forgot to write the .value in computed methods:
computed: {
products() {
return this.element.config.products.value;
}
},
However I also found such function call in shopware source codes which was not mentioned in the docs:
methods: {
createdComponent() {
this.initElementConfig('youtube-video');
this.initElementData('youtube-video'); // this line was not present in docs
}
}
I assume you haven't done any further handling of the product data in your config component, as you do not mention it.
I suggest having a look at the default cms components like for example shopware/administration/Resources/app/administration/src/module/sw-cms/elements/product-slider/config/index.js where you can see how product data is handled :)

Is it possible to look within the at element in pages?

is it possible to look for elements only within the "At-Element" ?
Example Page:
class SearchDialogPage extends Page {
static at = { $('div', class: 'modalOverlay').has('div', class: 'contentbox__title', text: 'Search for Company') }
static content = {
nameTextline { $('div').has('label', text:'Name').$('input') module TextInput }
}
} }
I find more than one element for nameTextline, so i want to tell the Page, that it has to look into the div-Element declared in the "at" field.
Semantically, at is not a content element but a boolean condition, i.e. whatever code you have inside there will be evaluated as a "Groovy truthy" value. You should define your element in the content section, then refer to it from your at condition, not the other way around.

How to style features depending on comparison operators in Leaflet

All the examples I find online that talk about how to style a feature depending on one of its properties use a switch statement that evaluates whether that property corresponds to a specific value.
For example this is taken form one of Leaflet's official tutorials:
L.geoJSON(states, {
style: function(feature) {
switch (feature.properties.party) {
case 'Republican': return {color: "#ff0000"};
case 'Democrat': return {color: "#0000ff"};
}
}
}).addTo(map);
What if I wanted to determine the feature's color depending on a numeric treshold? Say all features that have propertyX (which is a number) bigger than a certain value get colored red, otherwise blue.
I found this post where one user explains that switch statements are not made for comparisons; how can I do one then?
If use an external function (see code below) the latter seems to not be able to access the feature's properties.
L.geoJSON(states, {
style: styling
}).addTo(map);
function styling () {
if (feature.properties.numericProp > 100) {
return {color: "red"}
} else {
return {color: "blue"}
}
}
The feature gets passed a parameter of your function, you forgot to add it:
function styling (feature) {
// feature is now available
}

Changing anyMatch default for Filter.JS in ExtJS for MultiSelect search

I have a multiselect bound to a store in which I implemented use of anyMatch: true to allow for True to allow any match - no regex start/end line anchors will be added (as per the comment in Filter.js). My problem is that I need to implement this as per the answer to multiselect-search-whole-string, in particular the solution provided in this fiddle https://fiddle.sencha.com/#fiddle/jf5
What I want to do is just set anyMatch: true, regardless, so I set it in Filter.js, but this has no effect on use of it. I searched the entire codebase for other instances of anyMatch: false and the only other one is in ext-all-debug.js. Why isn't setting these values having any effect? I don't see where else this default value could be set?
EDIT 1
I tried a different override, and while it is not exhibiting the right behavior, it is actually doing something this time. I figured that since the chunk of code that does work when embedded in the search attribute within the MultiSelector control was pretty much what was found in the MultiSelectorSearch's search method, that this was what I needed to focus on for the override. Any suggestions on tweaking this would be most welcome:
Ext.define('Ext.overrides.view.MultiSelectorSearch', {
override: 'Ext.view.MultiSelectorSearch',
search: function (text, me) {
var filter = me.searchFilter,
filters = me.getSearchStore().getFilters();
if (text) {
filters.beginUpdate();
if (filter) {
filter.setValue(text);
} else {
me.searchFilter = filter = new Ext.util.Filter({
id: 'search',
property: me.field,
value: text,
anyMatch: true
});
}
filters.add(filter);
filters.endUpdate();
} else if (filter) {
filters.remove(filter);
}
}
});
EDIT 2
Got it! The key was that originally, since this code was embedded in a singleton, I could reference the method by passing me from the calling form.panel. This did not work globally as an override, and required me to define the method as
search: function (text) {
var me = this,
I hope this helps someone out there!
Changing in ext-all-debug.js is not safe, when you do a production build this file will not get included.
Best way is to override the Filter class, here is how you can do it.
Ext.define('Ext.overrides.util.Filter', {
override: 'Ext.util.Filter',
anyMatch: true
});
And import this class in Application.js
Ext.require([
'Ext.overrides.util.Filter'
]);

Statically load a QML Component without instantiating it

As I understand it, a QML Component is like a kind of like a class in C++. It contains the definition of a QML object but isn't an instance of it. You can create a Component in these ways:
Creating a .qml file with the component name as its filename.
Define it inline with the Component { } syntax.
However these are actually two different things. The second one is more like a factory because you can do things like:
Component {
id: factory
Rectangle { width: 100; height:100; color: "red }
}
Component.onCompleted: {
var rect1 = factory.createObject(parent);
}
Whereas with the separate file you need to first load it into a factory like this:
var factory = Qt.createComponent("RedRectangle.qml")
var rect1 = factory.createObject(parent);
I'm only concerned with dynamic object creation, so this is not an option:
RedRectangle {
id: rect1
}
My question is: is there a way to create the objects dynamically, without having to create the Component factory dynamically too, and without having to specify the Component inline. I.e. I want the first example, but where the Rectangle is specified in another file.
I want this:
Component {
id: factory
url: "RedRectangle.qml"
}
Component.onCompleted: {
var rect1 = factory.createObject(parent);
}
Sadly that doesn't work. I also tried this:
Component {
id: factory
}
Component.onCompleted: factory.loadUrl("RedRectangle.qml");
But it doesn't work either. Am I being stupid or is this just not supported?
Here is some encapsulation:
Fact.qml (for some reason it doesn't let me name it Factory)
QtObject {
property string url
readonly property Component component : Qt.createComponent(url)
function get() { return component }
function load(url) { return Qt.createComponent(url) }
}
usage:
Fact {
id: f
url: "RedRect.qml"
}
StackView {
id: stack
}
Component.onCompleted: {
stack.push(f.component) // redrect
f.url = "BlueRect.qml"
stack.push(f.get()) // bluerect, redundant but shorter
stack.push(f.load("GreenRect.qml")) // greenrect, f.component is still bluerect
}
It will only load the component when its component property is referenced and you can change the url to load other components with the same Fact instance. Also the auxiliary load() method, which returns a component without actually changing the one potentially cached.
Actually the answer is not too bad, though I still think Component should support specifying a url directly.
Here is my solution:
property var factory: Qt.createComponent("RedRectangle.qml")

Resources