Suppose i want to override a function inside the native code provided by Sencha in the file ext-all-debug.js.
The function is defined inside the Ext.util.Renderable-class and has the name cacheRefEls.
The overriding should take place inside the index.html of the project to make it easier to maintain for future releases.
I have already tried out the override solutions proposed inside this thread:
Steps to overriding Sencha ExtJS standard component functionality (Ext.tree.Panel & Ext.data.TreeStore as two examples)
My index.html looks as follows:
<html>
...
<script type="text/javascript">
Ext.define('Myapp.view.Renderable', {
override: 'Ext.util.Renderable',
cacheRefEls: function(el) {
console.log("in overider method");
//my adapted version of it
}
});
</script>
...
</html>
Unfortunately after accessing the localhost:8080 over Firefox-33 it is visible from the Firebug-2-Console-log that it still uses the native version of the function.
What am i missing here?
In ExtJS 5, you need to move these methods to the privates configuration.
You should have seen the error:
Public method "cacheRefEls" conflicts with private framework method declared by Ext.util.Renderable
You can still override the private method. In your case, the solution would be:
Ext.define('Myapp.view.Renderable', {
override: 'Ext.util.Renderable',
privates: {
cacheRefEls: function(el) {
console.log("in overider method");
//my adapted version of it
}
}
});
Related
How can d3.js (v4) be used with a Polymer 2.0 element?
Or how to use a library inside a class that already extends another class?
Trying to create a polymer d3 element to take advantage of polymer's two-way data binding and d3's syntax and functions. So that the data can be bound to a polymer property and passed to the d3.data() function?
Currently declaring d3 in the class returns undefined. Does the class need to be instantiated with d3 as a parameter? It seemed to work with Polymer 1.0. Another approach was to create a function outside of the class and call that but it's ugly. It would be nice to just use d3 inside the class.
Or is there a cleaner better way?
eg.
<script src="../../bower_components/d3/d3.js"></script>
var d3 = d3;
debugger; // hits this breakpoint first, and d3 is defined here and below
<dom-module id="my-app">
<template>
<svg id="svg"></svg>
</template>
<script>
class MyApp extends Polymer.Element {
static get is() { return 'my-app'; }
static get properties() {
return {
data: {
type: Object,
observer: '_dataChanged'
}
}
}
ready: {
var d3 = d3; // when it breaks here on the above breakpoint this is defined
debugger; // when it hits this breakpoint 2nd, d3 is undefined here and outside the class; what happened? how to scope it in?
}
_dataChanged(newValue, oldValue): {
var circle = d3.select(this.$.svg).data(newValue).enter().append(circle); //d3 undefined(! how to define?)
}
}
window.customElements.define(MyApp.is, MyApp);
</script>
</dom-module>
window.d3 is the way as you're loading the script in the global scope. You can load any external script asynchronously or synchronously.
To load it synchronously, just place the <script> tag in the <head>.
To load it asynchronously, you can add an load event listener to the <script> tag to do subsequent stuff when the load is completed.
Updated with solution (28.03.2017):
http://aurelia.io/hub.html#/doc/article/aurelia/framework/latest/app-configuration-and-startup/8
Have updated Aurelia docs with solution (scroll down a little).
Special thanks to Charleh for hint.
Question:
Aurelia has this nice feature calls enhance, which can help you enhancing specific parts of your application with Aurelia functional.
But can we have multiple enhance statements on the same page? It seems problematical.
Example:
Task: enhance first component on the page, then get some data from the server and enhance second component on the page with server data as binding context
HTML
<!DOCTYPE html>
<html>
<head>
<title>Title</title>
</head>
<body>
<my-component1></my-component1>
<my-component2></my-component2>
</body>
</html>
JS
import { bootstrap } from 'aurelia-bootstrapper-webpack';
bootstrap(function(aurelia) {
aurelia.use
.standardConfiguration()
.globalResources("my-component1", "my-component2");
aurelia.start().then((app) => {
// Enhance first element
app.enhance(null, document.querySelector('my-component1'));
// Get some data from server and then enhance second element with binding context
getSomeDataFromServer().then((data) => {
app.enhance(data, document.querySelector('my-component2'));
});
});
});
Result:
In the result we will enhance first component, but when it's time for the second one, Aurelia will try to enhance first component one more time!
It happens because of aurelia-framework.js _configureHost method.
So basically when you start enhance it starts this method with your element as an application host:
Aurelia.prototype.enhance = function enhance() {
var _this2 = this;
var bindingContext = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
var applicationHost = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1];
this._configureHost(applicationHost || _aureliaPal.DOM.querySelectorAll('body')[0]);
return new Promise(function (resolve) {
var engine = _this2.container.get(_aureliaTemplating.TemplatingEngine);
_this2.root = engine.enhance({ container: _this2.container, element: _this2.host, resources: _this2.resources, bindingContext: bindingContext });
_this2.root.attached();
_this2._onAureliaComposed();
resolve(_this2);
});
};
And inside the _configureHost we can see this if statement which is just checking if our app instance is already host configured then do nothing.
Aurelia.prototype._configureHost = function _configureHost(applicationHost) {
if (this.hostConfigured) {
return;
}
...
Problem
So the actual problem here is that any enhanced element automatically became an application host (root) and when you try to enhance another element with the same aurelia instance you will just end up enhancing the first element always.
Question
Is this some way around for the cases when I want to enhance several elements on the page?
There's a clue here:
this.root = engine.enhance({container: this.container, element: this.host, resources: this.resources, bindingContext: bindingContext});
this.root.attached();
The aurelia.enhance just wraps the TemplatingEngine instance's .enhance method.
You could just pull TemplatingEngine from the container and call .enhance on it passing the bindingContext since aurelia.enhance does just that (but adds the additional "host configure" step that you've already done via your first .enhance call).
So that bit might look like:
import { Container } from 'aurelia-dependency-injection';
let engine = Container.instance.get(TemplatingEngine);
engine.enhance({ container: Container.instance, element: document.querySelect('my-component2'), resources: (you might need to inject these too), bindingContext: someContext });
(disclaimer: I didn't test the above so it may not be accurate - also you probably need to pass the resources object in - you can inject it or pull it from the container - I believe the type is just Resources)
However - something to note: your my-component2 won't actually be a child of your host element my-component1. I'm not sure if that will cause issues further down the line but it's just a thought.
I'm still curious as to why you'd want to bootstrap an Aurelia instance and then have it enhance multiple elements on the same page instead of just wrapping all that server response logic inside the component's viewmodel itself?
Maybe you can give a bit more context to the reason behind this?
My workaround for this issue for now (thanks to Charleh for the clue):
import { bootstrap } from 'aurelia-bootstrapper-webpack';
import {TemplatingEngine} from "aurelia-framework";
let enhanceNode = function (app, node, bindingContext = null) {
let engine = app.container.get(TemplatingEngine);
let component = engine.enhance({container: app.container, element: node, resources: app.resources, bindingContext: bindingContext});
component.attached();
}
bootstrap(function(aurelia) {
aurelia.use
.standardConfiguration()
.globalResources("my-component1", "my-component2")
aurelia.start().then((app) => {
enhanceNode(document.querySelector('my-component1'));
enhanceNode(document.querySelector('my-component2'));
});
});
That way you can skip host configuration for the app and can enhance as many custom elements as you want on the page.
I trying to adopt the demo in this article http://www.asp.net/signalr/overview/getting-started/tutorial-high-frequency-realtime-with-signalr which is developed with vS2012, however I am using vs2010.
I made the model:
[HubName("moveShapeHub")]
public class MoveShapeHub : Hub
{
public void UpdateModel(ShapeModel clientModel)
{
clientModel.LastUpdatedBy = Context.ConnectionId;
Clients.AllExcept(clientModel.LastUpdatedBy).updateShape(clientModel);
}
}
Modified Global.cs:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
RouteTable.Routes.MapHubs();
}
In the view:
var moveShapeHub = $.connection.moveShapeHub,
$shape = $("#shape"),
shapeModel = {
left: 0,
top: 0
};
moveShapeHub.client.updateShape = function (model) {
shapeModel = model;
$shape.css({ left: model.left, top: model.top });
};
$.connection.hub.start().done(function () {
$shape.draggable({
drag: function () {
shapeModel = $shape.offset();
moveShapeHub.server.updateModel(shapeModel);
}
});
I get the following error:
Unable to get property 'client' of undefined or null reference.
Any idea what I am doing wrong; would appreciate your suggestions.
It looks like you're not including the following code in your HTML:
<script src='/signalr/hubs'></script>
Make sure that that code snippet is included AFTER your inclusion of the signalr js library.
If you're still adding the script tag correctly then you're having a path misunderstanding issue where your server is being hosted on a different port.
Lets say your sample is running on http://localhost:1337, you can view your signalr/hubs file by going to http://localhost:1337/signalr/hubs in your browser and you should get generated JavaScript.
A common issue that people run into is they include the /signalr/hubs file but they host their site on http://localhost:1337/bar/. Therefore SignalR tries to load the hubs file from http://localhost:1337/signalr/hubs when really it's located at http://localhost:1337/bar/signalr/hubs.
Verify that your inclusion of /signalr/hubs is pointing to the correct location. I usually do:
<script src="<%: ResolveUrl("~/signalr/hubs") %>"></script>
To always resolve the App-relative URL.
Also be sure to call RouteTable.Routes.MapHubs(); BEFORE you map any other routes.
Have you verified that connection is being established with the server, if not add a .fail(function(){
alert("failed to connect")}); to the end of your connection.hub.start method, to see if it is connecting ok, afterwards try this method:
moveShapeHub.on('updateShape', function(model) {
shapeModel = model;
$shape.css({ left: model.left, top: model.top });
});
I found the way to implement listeners for components in EXTJS MVC. But I cannot find the way to add listeners for grid plugins at controller.
not sure if it can help you, I my self now use ComponentQuery directly to retrieve currently edited field.. check it..
ExtJS 4 - How to listen event of each field within roweditor inside controller
The below example worked for me. That is to say, I can now handle plugin events in my controller. Since I was developing a custom plugin and you are using a packaged plugin, your approach will be a little different. I think you should extend the plugin that you want to use, adding the "mixins" and "relayEvents" concepts from my example. You could also create an override for the plugin you are using.
Ext.define( "Ext.ux.MyController", {
extend: "Ext.app.Controller",
init: function() {
this.control( {
"mycomponentxtype": {
"load": function(){ ... },
"unload": function(){ ... }
}
} )
}
} );
Ext.define( "Ext.ux.MyPlugin", {
extend: "Ext.AbstractPlugin",
alias: "plugin.myplugin",
mixins: [
"Ext.util.Observable"
],
config: {
...
},
init: function( myComponent ) {
var me = this;
// contruction of the mixin is required.
me.mixins["Ext.util.Observable"].constructor.call( me );
myComponent.relayEvents( me, [ "load", "unload" ] );
.
.
.
}
} );
Even though the original question is from early 2013. I came to this post in mid-2014 in search of an adequate answer and did not find it. This is essentially how I solved my problem. I hope it helps!
This has been answered, though specifically for rowEditing plugin, it should be applicable to any plugin:
Ext JS 4 - How to control rowEditor inside controller
I'm using underscore and backbone on a multi page site with a couple of underscore templates on each page. On my main view(cshtml) I load one javascript template like this http://cl.ly/GpFT and on my second view(cshtml) I use the same script setup but the javascript template is missing and then I get an error like this http://cl.ly/Gnrc
When I minify my scripts this will cause the script to abort. Is it possible to solve this in a nice way or do I need to load exactly the templates and scripts needed for each and every page?
You don't tell us what your views look like so I'll assume that you're doing something like this:
var V = Backbone.View.extend({
template: _.template($('#some-id').html()),
//...
});
and your views are raising TypeErrors when you're loading them. If there is no #some-id in the DOM, then you'll be saying _.templates(null) and that doesn't make any sense. An easy way around this to compile the template in the view's constructor instead:
var V = Backbone.View.extend({
initialize: function() {
this.template = _.template($('#some-id').html());
//...
},
//...
});