Skip to content

Commit

Permalink
More learning content
Browse files Browse the repository at this point in the history
  • Loading branch information
maxrahder committed Dec 17, 2023
1 parent c8d49bb commit a7b7cd1
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 41 deletions.
2 changes: 0 additions & 2 deletions apps/portal/view/learn/ContentTreeList.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ class ContentTreeList extends TreeList {
parentId: key,
appName: this.appName
})
console.log(foo);
});
}
}
Expand Down Expand Up @@ -169,7 +168,6 @@ class ContentTreeList extends TreeList {
me.deck = search.deck || 'learnneo';

me.doLoadStore();
console.log(search);
})
}

Expand Down
6 changes: 1 addition & 5 deletions apps/portal/view/learn/LivePreview.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class LivePreview extends Base {
* @protected
*/
className: 'Portal.view.learn.LivePreview',
cls: ['learn-live-preview'],
baseCls: ['learn-live-preview'],
value_: null,
autoMount: true,
autoRender: true,
Expand Down Expand Up @@ -132,8 +132,6 @@ class LivePreview extends Base {
.catch(error=>container.add({ntype:'component',html:error.message}));
`;

// console.log(codeString);

const container = this.getReference('preview');
container.removeAll();
try {
Expand Down Expand Up @@ -180,9 +178,7 @@ class LivePreview extends Base {
* @param {Number} data.value
*/
onActiveIndexChange(data) {
console.log('onActiveIndexChange', data)
if (data.item.reference !== 'preview') return;

this.doRunSource();
}
findLastClassName(sourceCode) {
Expand Down
58 changes: 55 additions & 3 deletions resources/data/deck/learnneo/p/Events.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,61 @@ class MainView extends Base {
Neo.applyClassConfig(MainView);
</pre>

It's important to keep in mind that in Neo.mjs, all class definitions are coded in their own
(It's important to keep in mind that in Neo.mjs, all class definitions are coded in their own
source file: one class per file. In the examples we're putting all the relevant classes together
to make it easier to see all the source code in one place. But in an
to make it easier to see the source code for every class being used. But in an
actual applications the controller class would be coded in its own source file &mdash; named something
like `MainViewController.mjs` &mdash; and that would be imported into the view.
like `MainViewController.mjs` &mdash; and that would be imported into the view.)

The ability to fire events and add listeners is provided by `Neo.core.Observable`, which is mixed into
classes that need that ability. All components are observable, `Neo.data.Store` is observable, and some
others. `Neo.core.Observable` introduces a few methods and properties, such as `listeners`, which
is used in the examples above, `on()` for procedurally adding an event listener, and `fire()`, which is
how you fire events in the custom classes you create.

Here's another example illustrating how you'd fire a custom `change` event. The code defines a `ToggleButton`
class, which is just a button with a `checked` property: the button shows a checked or unchecked
checkbox depending on the value of `checked`.

The code uses a special Neo.mjs feature you haven't seen yet &mdash; the use of an underscore property.
We'll discuss that at length later, but in a nutshell, config properties ending in an underscore
automatically get lifecycle methods run before the value is assigned, after the value is assigned, and
before the value is accessed. We're using the _after_ method to fire a `change` event.

<pre data-neo>
import Base from '../../../../src/container/Base.mjs';
import Button from '../../../../src/button/Base.mjs';
import TextField from '../../../../src/form/field/Text.mjs';

class ToggleButton extends Button {
static config = {
className: 'Example.view.ToggleButton',
checked_: false
}
afterSetChecked(checked){
this.iconCls = checked?'fa fa-square-check':'fa fa-square';
this.fire('change', {component: this, checked}); // This is where our custom event is being fired
}
onClick(data){
super.onClick(data);
this.checked = !this.checked;
}
}
Neo.applyClassConfig(ToggleButton);


class MainView extends Base {
static config = {
className : 'Example.view.MainView',
layout: {ntype:'vbox', align:'start'},
items : [{
module: ToggleButton,
text: 'Toggle',
listeners: {
change: data => console.log(data.checked) // Here, we're listening to the custom event
}
}]
}
}
Neo.applyClassConfig(MainView);
</pre>
50 changes: 19 additions & 31 deletions resources/data/deck/learnneo/p/References.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
Controllers may need to get references to components in order to update
the UI or access their properties.

Controllers often need to get references to components in order to update
the UI or access component properties.
There are two common ways of doing that:

- Using the component references passed to the event handler
Expand Down Expand Up @@ -84,53 +83,42 @@ Neo.applyClassConfig(MainView);
</pre>


There are other ways of getting references, but these are either non-standard or for debugging only.
There are other ways of getting references, but these are either non-standard or for debugging.
For example, components have an `up()` method, and containers have a `down()` method. These look
up or down the containment hierarchy to find the specified component. Doing this is poor technique
becuse it violates principles of encapsulation and limited &mdash; using those methods any component
anywhere in the app could be fetched.
up or down the containment hierarchy to find the specified component. Using these methods is poor technique
becuse it violates principles of encapsulation and limiting scope.

There are also handy debugging methods, such as `Neo.findFirst()` which will find any component matching
the search param. Try it out &mdash; the code uses `findFirst()` to get a reference to the _Learn_
button at the top of this page, then updates its `text`.
There are also debugging methods, such as `Neo.findFirst()` which will find any component matching
the search param.

When you're debugging it's pretty handy to be able to inspect or interact with any component in the app.
But app logic should never use `Neo.findFirst()` and very very rarely use `up()` or `down()`.
But app logic should never use `Neo.findFirst()` and very rarely use `up()` or `down()`.

The following example gets a reference to the _Learn_ button at the top of this site, and changes its `text`.
Again &mdash; that use of `Neo.findFirst()` might be handy when debugging, but it should never be used in app logic.

<pre data-neo>
import Base from '../../../../src/container/Base.mjs';
import Controller from '../../../../src/controller/Component.mjs';
import Button from '../../../../src/Button/Base.mjs';

class MainViewController extends Controller {
static config = {
className: 'Example.view.MainViewController'
}
onUpdateLearnTextClick(data){
const component = Neo.findFirst({text:'Learn'});
if (component) component.text = 'Yikes!';
}
onRestoreLearnTextClick(data){
const component = Neo.findFirst({text:'Yikes!'});
if (component) component.text = 'Learn';
}
}
Neo.applyClassConfig(MainViewController);


class MainView extends Base {
static config = {
className : 'Example.view.MainView',
controller: MainViewController,
layout: {ntype:'vbox', align:'start'},
items : [{
module: Button,
text: 'Change Learn caption',
handler: 'onUpdateLearnTextClick'
handler: data=>{
const component = Neo.findFirst({text:'Learn'});
if (component) component.text = 'Yikes!';
}
}, {
module: Button,
text: 'Restore Learn caption',
handler: 'onRestoreLearnTextClick'
handler: data=>{
const component = Neo.findFirst({text:'Yikes!'});
if (component) component.text = 'Learn';
}
}]
}
}
Expand Down

0 comments on commit a7b7cd1

Please sign in to comment.