How to set target anchor when creating a link - jointjs

I'm trying to set a specific anchor point when creating a link. I believe I'm doing everything correctly, but the anchor options are being ignored. In fact, any options I pass in are being ignored.
My code looks something like this:
new joint.shapes.standard.Link().target({id: 'xxx'}, {
anchor: {
name: 'center',
args: { dy: -15 }
}
});
The target id is being correctly handled, but whatever I pass in the second parameter is totally ignored.
Has anyone come across this before?

After experimenting, I worked out that when passing an object with id, rather than parsing a target element, that the opts need to go inside the object with the id. This is not documented AFAIK.
i.e.
.target({id: element.id, opts})
In my specific case, I'm passing the following:
.target({ id: to.id, anchor: { name: 'center', args: { dy: -15 }}})
This seems to work correctly

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 :)

How to update the data in an ng2-chartjs2 chart in Angular 2 and Node JS

I am using NodeJS, Angular2, and the ng2-chartjs2. Below I listed the relevant parts of my code that is rendering charts. The data is loaded into this.data from an API using a fixed date range. I would like to allow the user to select a date range and then update the chart. From here I know that you can call update() on the chart object to update the data in it, but I don't know how to get a hold of the chart object, since the component code never actually has a reference to it - it's done automagically when the template is rendered. Looking at the source code (line 13) I see that the author intended to make the object available. I contacted the author but haven't received a response yet and need to get moving. I have learned a lot about Angular2 but am no expert yet, so perhaps a deeper understanding of Angular2 makes this obvious. How can I either get access to the object to call update() on it, or do it some other clean way?
The template contains
<chart [options]="simple.options"></chart>
and the component typescript code contains
import { ChartComponent } from 'ng2-chartjs2';
...
#Component({
selector: 'home',
templateUrl: 'client/components/home/home.component.html',
styleUrls: ['client/components/home/home.component.css'],
directives: [DashboardLayoutComponent, CORE_DIRECTIVES, ChartComponent],
pipes: [AddCommasPipe],
})
...
setCurrentSimpleChart = (simpleType: number): void => {
this.simple.options = {
type: 'line',
options: this.globalOptions,
data: {
labels: this.data[simpleType].labels,
datasets: [{
label: this.titles[simpleType],
data: this.data[simpleType].data,
backgroundColor: 'rgba(255, 99, 132, 0.2)',
borderColor: 'rgba(255,99,132,1)',
borderWidth: 1
}],
},
};
...
}
Update: In case this helps anyone: I actually have two different charts on the page, so I googled around based on the accepted answer and found ViewChildren, and mapped them to different variables so I can update them both separately, with
[this.simpleChart, this.liftChart] = this.chartComponents.toArray().map(component => component.chart);
(Note also that this was using an rc of angular2 - since then directives, etc have been moved out of the components themselves.)
You can hold reference to component by using ViewChild:
#ViewChild(ChartComponent) chartComp;
And then you can get chart object:
let chart = this.chartComp.chart;
Here is the corresponding plunker

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'
]);

Fabric: error loading subclass object from JSON

In this jsfiddle I have a line that is created from a subclass (it's basically a line with two additional attributes). I'm trying to serialize/deserialize the line to/from JSON. I can serialize with no problems (including the two additional attributes) but when I try to deserialize with loadFromJSON I get the Cannot read property 'async' of undefined exception.
Uncomment the last line in the jsfiddle to get the error.
I implemented the fromObject() method, but I'm not sure it's correct. What's wrong with this code?
Javascript:
var canvas = new fabric.Canvas('c');
fabric.PolySegment = fabric.util.createClass(fabric.Line, {
type: 'seg',
initialize: function(points,options) {
options || (options = { });
this.callSuper('initialize', points,options);
this.set('poly', options.poly);
this.set('id', options.id);
},
toObject: function() {
return fabric.util.object.extend(this.callSuper('toObject'), {
poly: this.get('poly'),
id: this.get('id')
});
},
_render: function(ctx) {
this.callSuper('_render', ctx);
}
});
fabric.PolySegment.fromObject = function (object, callback) {
return new fabric.PolySegment(object);
};
fabric.PolySegment.async = true;
var coords1 = [ 10, 10, 100, 100 ];
var seg1 = new fabric.PolySegment(coords1, {
stroke: 'black',
strokeWidth: 6,
originX: 'left',
originY: 'top',
poly: 111111,
id: 222222
});
canvas.add(seg1);
var json = JSON.stringify(canvas);
document.getElementById('t').innerHTML = json;
// uncomment the line below, you'll get an exception
//canvas.loadFromJSON(json);
In looking at your Fiddle, it seems like the issue is the type value you have given your new class. If I change:
type: 'seg',
to
type: 'polySegment',
and uncomment the last line, I don't get the error. However, I also don't get the line to load on the canvas. But I guess I'm not 100% sure what is happening in your script there - you're loading the polySegment, then converting it to JSON and reloading it? I'm assuming this is merely for illustration purposes.
While what I suggest here gets rid of your error, I'm personally not 100% sure why it works. In reading the FabricJS documentation on Subclassing, it doesn't specify that the subclass type needs to match that of the subclass definition, but it seems to work...
I hope that helps in some way.
One last comment about this, I've always used the toJSON method to transfer a canvas element to JSON. Though this retrieves a JSON object, not a string like you are doing. Also, the toJSON method requires that you specify what properties you want to capture, so maybe this isn't the best method for your case. It's discussed on this page. But my point for bringing this up, is I know for certain that the toJSON method works well with the loadFromJSON method. So I mention that in case you find the JSON.stringify method to be the issue, there is a alternate method to approach the same concept.

How to create a ribbon with FlamingoBuilder in Griffon?

I'm currently trying to create an application with Griffon 0.9.5 and the FlamingoBuilder.
I've the changed the value of frameClass in Application.groovy to 'org.jvnet.flamingo.ribbon.JRibbonFrame' and tried a few things in order to add a ribbon to the application window.
My first attempt was creating a ribbonTask node with nested ribbonBand nodes. The application starts but the buttons are not shown.
application(title: 'test01',
preferredSize: [320, 240],
pack: true,
locationByPlatform: true,
iconImage: imageIcon('/griffon-icon-48x48.png').image,
{
ribbonTask(title: 'Start') {
ribbonBand(id: 'fooBarBand', title: 'FooBar', image: imageIcon('/griffon-icon-48x48.png').image) {
commandButton(id: 'fooButton', text: 'Foo', image: imageIcon('/griffon-icon-48x48.png').image)
commandButton(id: 'barButton', text: 'Bar', image: imageIcon('/griffon-icon-48x48.png').image)
}
}
// add content here
label('Content Goes Here') // delete me
}
)
In my second attempt I explicitly create a RibbonTask and call addTask. The buttons are shown. However, I'm not sure if this is really the Griffon-way of doing things.
Question: Is there a better way to create a ribbon?
application(title: 'test01',
preferredSize: [320, 240],
pack: true,
locationByPlatform: true,
iconImage: imageIcon('/griffon-icon-48x48.png').image,
{
ribbonBand(id: 'fooBarBand', title: 'FooBar', image: imageIcon('/griffon-icon-48x48.png').image) {
commandButton(id: 'fooButton', text: 'Foo', image: imageIcon('/griffon-icon-48x48.png').image)
commandButton(id: 'barButton', text: 'Bar', image: imageIcon('/griffon-icon-48x48.png').image)
}
current.ribbon.addTask new RibbonTask('Start', fooBarBand)
// add content here
label('Content Goes Here') // delete me
}
)
I then tried adding a ribbonApplicationMenu with the following code snippet:
ribbonApplicationMenu(id: 'appMenu') {
ribbonApplicationMenuEntryPrimary(id: 'quitMenuEntry', text: 'Quit',
entryKind: JCommandButton.CommandButtonKind.ACTION_ONLY,
image: imageIcon('/griffon-icon-48x48.png').image)
}
However, it doesn't work. I get the following runtime exception:
java.lang.RuntimeException: Failed to create component for
'ribbonApplicationMenuEntryPrimary' reason:
groovy.lang.MissingPropertyException: No such property: text for
class:
griffon.builder.flamingo.factory.RibbonApplicationMenuEntryPrimaryFactory
The documentation of FlamingoBuilder states that there is a text property and when I remove the text property I get an exception because the text property must be set. I'm a little bit at loss. What's wrong with this code snippet?
I'm afraid the first issue is related to the application() node factory vs ribbonFrame() factory. You see, Griffon assumes the frame subclass to behave like any other regular JFrame however JRibbonFrame handles its children in a different way. This is not know to ApplicationFactory so it "fails" to add ribbon tasks unless you add them manually as you show in the second snippet.
This problem can be fixed by moving the parent/child relationship code from ribbonFrame() to ribbonBand/ribbonTask factories. This requires a new release of FlamingoBuilder.
Now on the second problem, that appears to be a bug on our side. Considering that FlamingoBuilder should be updated in any case we'll fix this problem too.

Resources