I'm using dynatree with selectMode = 3, when user clicks into a node that has a parent, I need to apply a class to the parent. Any idea how to do it?
This is my code:
function CheckUnCheckParents(flag, node) {
var pnode = node.getParent();
if (pnode != null) {
if (hasSelectedNodes(pnode)) {
**add class 'dynatree-selected' to the parent**
}
}
return false;
}
Set the addClass on the parent:
pnode.data.addClass = 'dynatree-selected'
Related
I want to use the ´bool DrawMode´ inside my ChangeDrawModeState class.
I need Something like ´GridState.drawMode´ but that does not work(drawMode is defined in GridState).
In the end I need to change the variable drawMode, if the RaisedButton gets Pressed. I'm not sure how to do this, cause the setState isnt working in the ChangeDrawModeState class as well. But isn't there a simple way to build a Button which turns a bool from True to false(or the other way around)?
class ChangeDrawMode extends StatefulWidget{
#override
ChangeDrawModeState createState(){
return new ChangeDrawModeState();
}
}
class ChangeDrawModeState<ChangeDrawMode>{
#override
Widget build(BuildContext context) {
return new RaisedButton(
child: new Text('Change Mode'),
textColor: Colors.white,
color: GridState.drawMode ? Colors.grey : Colors.blue,//HERE
onPressed: () =>setState(() => drawMode = !drawMode) //and HERE drawMode does not work
);
}
}
class Grid extends StatefulWidget {
#override
GridState createState() {
return new GridState();
}
}
class GridState extends State<Grid> {
bool drawMode = false;
final Set<int> selectedIndexes = Set<int>();
final key = GlobalKey();
final Set<_Foo> _trackTaped = Set<_Foo>();
_detectTapedItem(PointerEvent event) {
final RenderBox box = key.currentContext.findRenderObject();
final result = BoxHitTestResult();
Offset local = box.globalToLocal(event.position);
if (box.hitTest(result, position: local)) {
for (final hit in result.path) {
/// temporary variable so that the [is] allows access of [index]
final target = hit.target;
if (target is _Foo /*&& !_trackTaped.contains(target)*/) {
_trackTaped.add(target);
_selectIndex(target.index);
}
}
}
}
_selectIndex(int index) {
setState(
() {
if(selectedIndexes.contains(index)&&drawMode==false){
selectedIndexes.remove(index);
}
else if(drawMode==true){
selectedIndexes.add(index);
}
});
}
You can use InheritedWidget to update data and therefore widget state from any part of the app
Here is an example
I'd like to reproduce the behavior of the Java browsing perspective as so : the user select a file (selectedFile) from a Custom Common Navigator View (VariabilityNavigator) and it displays only the related files to that selection in another Custom Common Navigator View (ConfigFileNavigator). It refreshes automatically as the selection goes.
I use Common navigator because I want to display the package of the related files and not the other ones or the empty ones. That I coded fine.
Could you please walk me thru the steps to do that ? Here is how far I got..
I have successfully coded the first view VariabilityNavigator.
I thought I would use a filter ConfigurationFilesFilter to get the selectedFile and use it to filter the related files.
I can get the selection from the VariabilityNavigator within the select(...) of ConfigurationFilesFilter code below
I then use it to filter the files I want to display using isRelatedToSelection. I haven't write that part yet, but it's not a problem for testing.
This method don't work for several reasons : it doesn't refresh and I have to click on the ConfigFileNavigator to get the result. What it should do : when I click on the first view and it should automatically display the result in the second view. Thanks for your help.
public class ConfigurationFilesFilter extends ViewerFilter {
String selectedFile;
public ConfigurationFilesFilter() {
}
#Override
public boolean select(Viewer viewer, Object parent, Object element) {
selectedFile = getVariabilityNavigatorSelection();
if (isChildElement(element)) {
return handleChild(element);
} else {
// manipulate tree viewer based on select decision for the sub elements
StructuredViewer sviewer = (StructuredViewer) viewer;
ITreeContentProvider provider = (ITreeContentProvider) sviewer.getContentProvider();
for (Object child : provider.getChildren(element)) {
if (select(viewer, element, child)) {
return true;
}
}
return false;
}
}
/**
*
* #param element
* #return true to be displayed
*/
private boolean handleChild(Object element) {
return true;
}
/**
* Check if an element is a java file and if it is related to the selection
*
* #param element
* #return boolean
*/
private boolean isChildElement(Object element) {
if (element instanceof IFile) {
if (((IFile) element).getFileExtension().equals("java")) {
return (isRelatedToSelection((IFile) element));
}
return false;
}
return false;
}
public String getVariabilityNavigatorSelection() {
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
IViewPart viewPart = page.findView(VariabilityNavigator.ID);
String VariabilityNavigatorSelection = "" ;
if (viewPart == null) {
VariabilityNavigatorSelection = "open Variability view. \r\nTo do so, open the menu as followed:\r\nWindow > Show view > Other... > SPL > Variability Navigator";
} else {
ISelectionProvider selProvider = viewPart.getSite().getSelectionProvider();
IStructuredSelection sel = (IStructuredSelection) selProvider.getSelection();
if (sel.isEmpty()) {
VariabilityNavigatorSelection = "selection vide";
}
Iterator<?> i = sel.iterator();
while (i.hasNext()) {
final Object o = i.next();
if (o instanceof IFile) {
VariabilityNavigatorSelection = ((IFile) o).getName();
} else
VariabilityNavigatorSelection = "Please select a file";
}
}
if (!VariabilityNavigatorSelection.isEmpty())
printTrace("selectPrint = " + VariabilityNavigatorSelection);
return VariabilityNavigatorSelection;
}
I'd like to achieve something similar as "include" in android but in aurelia:
How to inject a plain html file content into my view, with binding evaluated within the parent View, and without using a custom element?
Binding innerhtml is not enough as, according to the doc, the bindings expressions are bypassed.
As already said by Ashley, using <compose view="./your-view.html"></compose> element will work with an existing HTML file and it will inherit the parent context.
If you want to compose HTML dynamically (from a file, database, or built-up programmatically) then using the ViewCompiler will give you the best performance and flexibility, as this is one layer less than compose compared to how aurelia builds custom elements internally.
I gave a similar answer to a different (but related) question here:
Aurelia dynamic binding
You'd use the text plugin to load your HTML file as text into a variable, and then pass that to the ViewCompiler. I have a custom element for this which, in terms of performance, is probably not better than compose but it does allow for more control when working with raw html as input and you could do your own performance optimizations specific to your situation as needed:
import * as markup from "text!./your-element.html";
export class SomeViewModel {
constructor() {
this.markup = markup;
}
}
And the view:
<template>
<dynamic-html html.bind="markup"></dynamic-html>
</template>
For completeness sake, here is the custom element I encapsulated the ViewCompiler in:
import {
customElement,
TaskQueue,
bindable,
ViewCompiler,
ViewSlot,
View,
ViewResources,
Container,
ViewFactory,
inlineView,
inject,
DOM
} from "aurelia-framework";
#customElement("dynamic-html")
#inlineView("<template><div></div></template>")
#inject(DOM.Element, TaskQueue, Container, ViewCompiler)
export class DynamicHtml {
#bindable()
public html: string;
public element: HTMLElement;
private tq: TaskQueue;
private container: Container;
private viewCompiler: ViewCompiler;
private runtimeView: View;
private runtimeViewSlot: ViewSlot;
private runtimeViewFactory: ViewFactory;
private runtimeViewAnchor: HTMLDivElement;
constructor(element, tq, container, viewCompiler) {
this.element = <HTMLElement>element;
this.tq = tq;
this.container = container;
this.viewCompiler = viewCompiler;
}
public bindingContext: any;
public overrideContext: any;
public bind(bindingContext: any, overrideContext: any): void {
this.bindingContext = bindingContext;
this.overrideContext = overrideContext;
if (this.html) {
this.htmlChanged(this.html, undefined);
}
}
public unbind(): void {
this.disposeView();
this.bindingContext = null;
this.overrideContext = null;
}
public needsApply: boolean = false;
public isAttached: boolean = false;
public attached(): void {
this.runtimeViewAnchor = <HTMLDivElement>this.element.firstElementChild;
this.isAttached = true;
if (this.needsApply) {
this.needsApply = false;
this.apply();
}
}
public detached(): void {
this.isAttached = false;
this.runtimeViewAnchor = null;
}
private htmlChanged(newValue: string, oldValue: void): void {
if (newValue) {
if (this.isAttached) {
this.tq.queueMicroTask(() => {
this.apply();
});
} else {
this.needsApply = true;
}
} else {
if (this.isApplied) {
this.disposeView();
}
}
}
private isApplied: boolean = false;
private apply(): void {
if (this.isApplied) {
this.disposeView();
}
this.compileView();
}
private disposeView(): void {
if (this.runtimeViewSlot) {
this.runtimeViewSlot.unbind();
this.runtimeViewSlot.detached();
this.runtimeViewSlot.removeAll();
this.runtimeViewSlot = null;
}
if (this.runtimeViewFactory) {
this.runtimeViewFactory = null;
}
if (this.runtimeView) {
this.runtimeView = null;
}
this.isApplied = false;
}
private compileView(): void {
this.runtimeViewFactory = createViewFactory(this.viewCompiler, this.container, this.html);
this.runtimeView = createView(this.runtimeViewFactory, this.container);
this.runtimeViewSlot = createViewSlot(this.runtimeViewAnchor);
this.runtimeViewSlot.add(this.runtimeView);
this.runtimeViewSlot.bind(this.bindingContext, this.overrideContext);
this.runtimeViewSlot.attached();
this.isApplied = true;
}
}
function createViewFactory(viewCompiler: ViewCompiler, container: Container, html: string): ViewFactory {
if (!html.startsWith("<template>")) {
html = `<template>${html}</template>`;
}
let viewResources: ViewResources = container.get(ViewResources);
let viewFactory = viewCompiler.compile(html, viewResources);
return viewFactory;
}
function createView(viewFactory: ViewFactory, container: Container): View {
let childContainer = container.createChild();
let view = viewFactory.create(childContainer);
return view;
}
function createViewSlot(containerElement: Element): ViewSlot {
let viewSlot = new ViewSlot(containerElement, true);
return viewSlot;
}
I've created a custom element that generates tabular data. For good reasons, this generates the actual HTML and inserts into the DOM without using a template.
I need to attach click observers to specific elements to I can run a function in the custom element in response to a click. If using a template, I'd use click.delegate, but I can't use that with generated HTML.
How do you attach an event handler with Aurelia other than by using jQuery?
I know this answer is late, but in case this hasn't been (properly) solved yet and/or someone else finds this in the future:
In order to make any aurelia behavior work in dynamically generated HTML, you need to compile that HTML.
I have worked on a custom element (based on how aurelia's enhance and compose work) that allows you to pass in a string of HTML and it will then be compiled, so that any behaviors like bindables, custom elements / attributes will just work. It will also re-compile when the html changes.
Here's an example: https://gist.run?id=1960218b52ba628f73774822aef55ad7
src/app.html
<template>
<dynamic-html html.bind="dynamicHtml"></dynamic-html>
</template>
src/app.ts
export class App {
public dynamicHtml: string = `
<button click.delegate="handleClick()">Click me</button>
`;
public handleClick(): void {
alert("Hello!")
}
}
src/dynamic-html.ts
import {
customElement,
TaskQueue,
bindable,
ViewCompiler,
ViewSlot,
View,
ViewResources,
Container,
ViewFactory,
inlineView,
inject,
DOM
} from "aurelia-framework";
#customElement("dynamic-html")
#inlineView("<template><div></div></template>")
#inject(DOM.Element, TaskQueue, Container, ViewCompiler)
export class DynamicHtml {
#bindable()
public html: string;
public element: HTMLElement;
private tq: TaskQueue;
private container: Container;
private viewCompiler: ViewCompile;
private runtimeView: View;
private runtimeViewSlot: ViewSlot;
private runtimeViewFactory: ViewFactory;
private runtimeViewAnchor: HTMLDivElement;
constructor(element, tq, container, viewCompiler) {
this.element = <HTMLElement>element;
this.tq = tq;
this.container = container;
this.viewCompiler = viewCompiler;
}
public bindingContext: any;
public overrideContext: any;
public bind(bindingContext: any, overrideContext: any): void {
this.bindingContext = bindingContext;
this.overrideContext = overrideContext;
if (this.html) {
this.htmlChanged(this.html, undefined);
}
}
public unbind(): void {
this.disposeView();
this.bindingContext = null;
this.overrideContext = null;
}
public needsApply: boolean = false;
public isAttached: boolean = false;
public attached(): void {
this.runtimeViewAnchor = this.element.firstElementChild;
this.isAttached = true;
if (this.needsApply) {
this.needsApply = false;
this.apply();
}
}
public detached(): void {
this.isAttached = false;
this.runtimeViewAnchor = null;
}
private htmlChanged(newValue: string, oldValue: void): void {
if (newValue) {
if (this.isAttached) {
this.tq.queueMicroTask(() => {
this.apply();
});
} else {
this.needsApply = true;
}
} else {
if (this.isApplied) {
this.disposeView();
}
}
}
private isApplied: boolean = false;
private apply(): void {
if (this.isApplied) {
this.disposeView();
}
this.compileView();
}
private disposeView(): void {
if (this.runtimeViewSlot) {
this.runtimeViewSlot.unbind();
this.runtimeViewSlot.detached();
this.runtimeViewSlot.removeAll();
this.runtimeViewSlot = null;
}
if (this.runtimeViewFactory) {
this.runtimeViewFactory = null;
}
if (this.runtimeView) {
this.runtimeView = null;
}
this.isApplied = false;
}
private compileView(): void {
this.runtimeViewFactory = createViewFactory(this.viewCompiler, this.container, this.html);
this.runtimeView = createView(this.runtimeViewFactory, this.container);
this.runtimeViewSlot = createViewSlot(this.runtimeViewAnchor);
this.runtimeViewSlot.add(this.runtimeView);
this.runtimeViewSlot.bind(this.bindingContext, this.overrideContext);
this.runtimeViewSlot.attached();
this.isApplied = true;
}
}
function createViewFactory(viewCompiler: ViewCompiler, container: Container, html: string): ViewFactory {
if (!html.startsWith("<template>")) {
html = `<template>${html}</template>`;
}
let viewResources: ViewResources = container.get(ViewResources);
let viewFactory = viewCompiler.compile(html, viewResources);
return viewFactory;
}
function createView(viewFactory: ViewFactory, container: Container): View {
let childContainer = container.createChild();
let view = viewFactory.create(childContainer);
return view;
}
function createViewSlot(containerElement: Element): ViewSlot {
let viewSlot = new ViewSlot(containerElement, true);
return viewSlot;
}
Any idea how to configure SortedList whose elements are components register on the container in binsor.
Crud:ICrud
{
public SortedList<string, ICrudTransfer> Proxies
{
get { return _proxies;}
set { _proxies = value; }
}
}
I would like to do something like:
component ‘proxy1′, ICrudTransfer
component ‘proxy2′, ICrudTransfer
_proxies = SortedList[of string, ICrudTransfer]()
_proxies['url1']=#proxy1
_proxies['url2']=#proxy2
component ’service’, ICrud, Crud:
Proxies = _proxies
But it doesn't work
I would like to use such as properties, arrays or list. That works
component ’service’, ICrud, Crud:
CrudProxy = #proxy3
CrudProxies = (#proxy1 , #proxy2)
Thanks
Solution:
public class TestClass:ITestClass
{
IDictionary<string, IClass1> _dictGen = null;
IList<IClass1> _listGen = null;
public IList<IClass1> ListGeneric
{
get { return _listGen; }
set { _listGen = value; }
}
public IDictionary<string, IClass1> DictionaryGeneric
{
get { return _dictGen; }
set { _dictGen = value; }
}
}
component 'c1', IClass1, Class1
component 'c2', IClass1, Class1
component 'd', ITestClass, TestClass:
DictionaryGeneric = {key1:#c1,key2:#c2}
ListGeneric = (#c1,#c2)
Without generic (IList or IDictionary) seem not to work.