coldbox-modules / cbwire

CBWIRE is a ColdBox module that makes building reactive, modern apps easy using HTML-over-the-wire technologies and CFML.
https://cbwire.ortusbooks.com
Other
28 stars 5 forks source link

Automatically populate data properties with passed parameters when onMount() isn't defined #131

Closed mrigsby closed 10 months ago

mrigsby commented 10 months ago

I ran into an issue the other day when I passed parameters to a wire and neglected to add an onMount() event. The wire threw an error about not having a setter for my parameter.

I was looking at how cbwire handles onMount() in /models/concerns/OnMountConcern.cfc and was thinking about how this might be handled differently.

Building on box products' love of conventions, I was thinking about an option where if onMount() does not exist, it checks that each parameter is a string, boolean, numeric, date, array, or struct and if they are cbwire populates the component using scope population instead of setters.

This would allow us to skip the onMount() function if we want to just merge basic parameters directly into the data property.

@grantcopley, am I missing something else this might affect? I know there might be a minor hit in performance if passing in a large number of parameters however, this can be negated by just adding the onMount() function and manually handling parameters.

// check datatypes parameters and throw error if not string, boolean, numeric, date, array, or struct
for( var paramKey IN arguments.parameters.keyArray() ){
    if(     !isSimpleValue( arguments.parameters[ paramKey ] ) 
        && !isArray( arguments.parameters[ paramKey ] ) 
        && !isStruct( arguments.parameters[ paramKey ] )
    ){
        throw( 
            type    = "MissingOnMount", 
            message = "The wire does NOT have an onMount() function and the paramaters passed contain a 
                data type other than string, boolean, numeric, date, array, or struct and cannot 
                be automatically inserted into the data properties. To avoid this error create an 
                onMount() method to handle incoming paramaters" 
        );
    }
}

// if parameters passed in are string, boolean, numeric, date, array, or struct insert into variables.data
getPopulator().populateFromStruct(
    target: comp.getParent(),
    memento: arguments.parameters,
    scope: "variables.data"
);
grantcopley commented 10 months ago

@mrigsby Good idea! I never thought about handling the params automatically. I am surprised that it threw an error if you didn't define an onMount() method. Could you include the error here?

As far as a feature though, let's add it. We can get it added and target it for the 3.2 release.

grantcopley commented 10 months ago

@mrigsby OK I see it now in https://github.com/coldbox-modules/cbwire/blob/development/models/concerns/OnMountConcern.cfc. In my testing, I've just always defined onMount() and therefore never ran into the ELSE block. Definitely makes sense now why it errored.

} else {
            /**
             * Use setter population to populate our component.
             */
            getPopulator().populateFromStruct(
                target: this,
                trustedSetter: true,
                memento: arguments.parameters,
                excludes: ""
            );
        }
mrigsby commented 10 months ago

Awesome, I just submitted a pull request! Let me see if I can recreate the error. I believe the culprit is that /models/concerns/OnMountConcern.cfc runs populateFromStruct() if there is no onMount() and uses trustedSetter = true which calls the setters even if they don't exist.

getPopulator().populateFromStruct(
    target: this,
    trustedSetter: true,
    memento: arguments.parameters,
    excludes: ""
);
mrigsby commented 10 months ago

Pull request merged. Closing issue

See PR #132

mrigsby commented 10 months ago

Closed