How to execute some init after element loaded to dom with Binding.scala - scala.js

#dom
def chart(show: Var[Boolean]) = {
if(show.bind) {
<canvas id="chartCanvas"><canvas>
}
}
How can I init the canvas with some chart library like chartjs when it is loaded to dom ?

Solution 1
#dom
def chart(show: Var[Boolean]) = {
if(show.bind) {
val myCanvas = <canvas id="chartCanvas"><canvas>
myInitializationCode(myCanvas)
myCanvas
} else {
<!-- don't show canvas -->
}
}
Solution 2
You can create a custom SingleMountPoint, and put the initialization code in the overriden mount method:
val yourCustomMountPoint = new SingleMountPoint[Boolean](show) {
override def mount() = {
super.mount()
// Your custom initialization code
}
override def unmount() = {
// Your custom clean up code
super.unmount()
}
override def set(newValue: Boolean) = {
// Your custom handler when `show` get changed
}
}
// Inject your custom mount point into the rendering process
yourCustomMountPoint.bind

Related

Mixed Jetpack Compose / Activity app navigation: from compose to activity and back

I am a newbie in Android development so I might be missing something simple here.
I have a compose setup using androidx.navigation:navigation-compose:2.5.3 where I have the routing setup:
sealed class Routes(val route: String) {
object Login : Routes("Login")
object TermsOfService : Routes("TermsOfService")
object Home : Routes("Home")
}
#Composable
fun Routing(startDestination: String) {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = startDestination) {
composable(Routes.Login.route) {
LoginPage(navController = navController, LoginViewModel(AppEnvironment.sdk))
}
composable(Routes.TermsOfService.route) {
TermsOfService(navController = navController)
}
composable(Routes.Home.route) {
Home(navController = navController)
}
}
}
I would setup my MainActivity:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
App_SenderTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
val isLoggedIn = AppEnvironment.encryptedSettingsRepo.isUserLoggedIn.get().toBoolean()
println("Routing based on is_user_logged_in $isLoggedIn")
if (isLoggedIn) {
Routing(startDestination = Routes.Home.route)
} else {
Routing(startDestination = Routes.Login.route)
}
}
}
}
}
}
The Home itself is an Activity setup like:
#Composable
fun Home(navController: NavHostController) {
Box(modifier = Modifier.fillMaxSize()) {
ScaffoldWithTopBarHome(navController)
}
}
#SuppressLint("UnusedMaterialScaffoldPaddingParameter")
#Composable
fun ScaffoldWithTopBarHome(navController: NavHostController) {
Scaffold(
topBar = {
CustomTopAppBar(navController, "Sender", true)
}, content = {
Column(
modifier = Modifier
.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
val context = LocalContext.current
context.startActivity(Intent(context, HomeActivity::class.java))
}
})
}
class HomeActivity : AppCompatActivity() {
fun logout() {
// HOW TO GO BACK TO COMPOSE IF I DON'T HAVE A COMPOSE NAVIGATION REFERENCE
}
}
I can easily navigate to the HomeActivity from any composable setup since I have the NavHostController, e.g. navController.navigate(Routes.Home.route), but how can I navigate back from the "activityworld` back to compose land.
Thanks.

How to Register custom handelbars helper in assemble 0.17.1

In my assemblefile.js I try to register a custom helper. The helper itself does work since i have it in use in a grunt project with assemble.
assemble: {
options: {
helpers: ['./src/helper/custom-helper.js' ]
}
}
In assemble 0.17.1 I tried it like this but it doesn´t work. Does anyone know how to do this?
app.helpers('./src/helper/custom-helper.js');
custom-helper.js:
module.exports.register = function (Handlebars, options, params) {
Handlebars.registerHelper('section', function(name, options) {
if (!this.sections) {
this.sections = {};
}
this.sections[name] = options.fn(this);
return null;;
});
};
assemble is built on top of the templates module now, so you can use the .helper and .helpers methods for registering helpers with assemble, which will register them with Handlebars. This link has more information on registering the helpers.
Since the templates api is used, you don't have to wrap the helpers with the .register method in your example. You can just export the helper function, then name it when registering with assemble like this:
// custom-helper.js
module.exports = function(name, options) {
if (!this.sections) {
this.sections = {};
}
this.sections[name] = options.fn(this);
return null;
};
// register with assemble
var app = assemble();
app.helper('section', require('./custom-helper.js'));
You may also export an object with helpers and register them all at once using the .helpers method:
// my-helpers.js
module.exports = {
foo: function(str) { return 'FOO: ' + str; },
bar: function(str) { return 'BAR: ' + str; },
baz: function(str) { return 'BAZ: ' + str; }
};
// register with assemble
var app = assemble();
app.helpers(require('./my-helpers.js'));
When registering the object with the .helpers method, the property keys are used for the helper names

Propagate / delegate path value to child routes akka http

I want to have a base route that receive a IntNumber and make some checks with the database to know if the values is correct or not and then If the value is correct I want to propagate the value to child routes.
Base Route
class BaseServiceRoute extends PathDirectives with SecurityDirectives {
val baseUserRoute = pathPrefix("user" / IntNumber)
}
How can I make some checks for the value IntNumber and the delegate the value to the child route? Directives?
Child Route
class CategoryServiceRoute(implicit executionContext: ExecutionContext) extends BaseServiceRoute {
val route = baseUserRoute { userId =>
pathPrefix("category") {
pathEndOrSingleSlash {
get {
complete(s"$userId")
}
} ~
path(LongNumber) { categoryId =>
get {
complete(s"$categoryId")
} ~
post {
complete("Hello category post")
}
}
}
}
}
Thanks
The best-practice suggestion would be just to nest the routes so that you can still access the value from the outer route like this:
pathPrefix("user" / IntNumber) { userId =>
pathPrefix("category") {
pathEndOrSingleSlash {
get {
complete(s"$userId")
}
}
}
}
However, you seem to want to separate routes into multiple parts which is perfectly fine. In that case just make the child route a def:
def childRoute(userId: Int): Route =
pathPrefix("category") {
pathEndOrSingleSlash {
get {
complete(s"$userId")
}
}
}
and then use it like this:
baseUserRoute(childRoute)

How to render a view from inside of a controller

From inside of a controller action I want to render a view, is this possible?
Example:
def index: Action {
val html: String = // render some action here
}
def index: Action {
val html: String = views.html.foo().body
}
Or
def index: Action {
val html: String = views.html.foo().toString
}

call parent class function on extjs 3

i have extjs class like this for Add:
Ext.ns('Example');
Example.Form = Ext.extend(Ext.form.FormPanel, {
,initComponent:function() {
// hard coded - cannot be changed from outsid
var config = {
items: [{
xtype: 'textfield',
fieldLabel: 'title',
name: 'author',
allowBlank: false
}
.........................
]
,buttons:[
{
text:'submit'
,formBind:true
,scope:this
,handler:this.submit
}]
}; // eo config object
// apply config
Ext.apply(this, Ext.apply(this.initialConfig, config));
// call parent
Example.Form.superclass.initComponent.apply(this, arguments);
} // eo function initComponent
/**
* Form onRender override
*/
,onRender:function() {
..................
} // eo function onRender
/**
* Reset
*/
,reset:function() {
this.getForm().reset();
} // eo function onRender
/**
* Load button click handler
*/
,onLoadClick:function() {
....................
}
,submit:function() {
........................
}
,onSuccess:function(form, action) {
..........................
}
,onFailure:function(form, action) {
......................
} // eo function onFailure
,showError:function(msg, title) {
........................
});
}
});
and i have another extend for Edit:
Example.Form2 = Ext.extend(Example.Form, {
......
});
how i can call "onLoadClick" function from first class in secound class?because i want to load data to my form before form load.
If you have one class that extends another class you can call the "parent" class methods by using the superclass property on your class definition.
In the example below we add a special function mySpecial add and make it call the parent classes add function.
Ext.ux.myForm = Ext.extend(Ext.form.FormPanel, {
...
mySpecialAdd: function(comp, anExtraParam) {
// some special handling here
...
// call parent class add
return Ext.ux.myForm.superclass.add.call(this, comp);
}
})
instead of call you can also choose to use apply
Ext.ux.myForm = Ext.extend(Ext.form.FormPanel, {
...
mySpecialAdd: function(comp, anExtraParam) {
// some special handling here
...
// call parent class add
return Ext.ux.myForm.superclass.add.apply(this, [comp]);
}
})
Do note that "this" will still be your new class, so any other function that you overwrite will be the one called from the parent class and not the parent class function.
Example
Ext.form.FormPanel have an onAdd method that is being called in Ext.form.FormPanel.add, so if you overwrite onAdd then its your function that is called.
Ext.ux.myForm = Ext.extend(Ext.form.FormPanel, {
...
mySpecialAdd: function(comp, anExtraParam) {
// some special handling here
...
// call parent class add
return Ext.ux.myForm.superclass.add.apply(this, [comp]);
},
// even though onAdd is marked as private you are actually still overwriting it here
// because of the way its implemented in Ext 3
onAdd: function(c) {
// this will get called from the parent class (Ext.form.FormPanel) add method.
...
// so make sure you handle it nicely
Ext.ux.myForm.superclass.onAdd.call(this, c);
...
}
})
If you need to call a superclass method into a method of the subclass, you can do something like this:
Example.Form2 = Ext.extend(Example.Form, {
testMethod: function(){
...
//call parent class method
Example.Form2.superclass.doLoadClick.call(this);
...
}
});
Is that what you mean ?