Create TV by snippet - assign to template

Hi there.

I’m using the latest Modx version 2.7.1 and grab data from a custom table with a snippet.

In this table there are different rows with data from “accounts” which have a related number. I want to create as many TVs with the same name and number as the accounts have.

This is working so far, the snippet reads the accounts and numbers off the custom table and does write a new row in modx_site_tmplvars.

My problem now is that these by snippet created TVs are not assigned to any template. This happens in modx_site_tmplvar_templates. Not that big issue if the IDs of the TVs from modx_site_tmplvars would be used in modx_site_tmplvar_templates as well. But the IDs are not used there, don’t get why tbh.

It seems that if i assign one of these by snippet created TVs to a template, a new row appears in modx_site_tmplvar_templates with a “tmplvarid”. But this tmplvarid is not the same as the TV-ID in the other table modx_site_tmplvars. It seems like it’s the row-number gets used as the “tmplvarid”?!? What the Heck?

Any one knows how i can be able to assign the create TVs to a template in a snippet?

Cheers in advance for any Ideas…

1 Like

First a question: what are this TVs. you want to create, for?

1 Like

Hey Bruno!

Thanks for your will to help!

The TVs i created are simple checkboxes with only one option: choose==[[+Name-of-the-account]]

These TVs shall be selectable in different resouces. The are “holding” just a placeholder for the different accounts. These placeholders output the value of the accounts, which then get calculated by another snippet to retrieve the result of the chosen TVs. The placeholders are getting created in the same snippet, before the TVs get written to the db.

Hope this helps…

Greetings to you!

P.S.: it might be that some day some more accounts are getting added. Because i dont want the customer to create a new TV by himself or inform me to create a new TV, i want to automate this somehow, that these new TVs get created without any editing by hand.

wouldn’t it be better to have just one checkbox-TV, which fetches the accounts with @SELECT or @CHUNK binding instead of creating one TV for each account?
I would store the ids, not the name of the account into the TV, btw

Hi again!

wouldn’t it be better to have just one checkbox-TV, which fetches the accounts with @SELECT or @CHUNK binding instead of creating one TV for each account?

I’m not sure if I get you correct with the @SELECT or @CHUNK binding - never used those before. I’m gonna check this out…

I would store the ids, not the name of the account into the TV, btw

I guess I described this bad, these TVs are only named like [[+Account_00100]], [[+Account_00450]], etc.

But maybe I have to think the whole thing over and maybe chose another approach.

In general I want to have different tables on the front-end. The “names” of the rows and columns shall be freely editable for the customer, but I guess they won’t get renamed that often than the default-table I am going to create. So far not a big problem.

But then each table-cell shall output a result of different calculations, based on the different accounts that are available in the custom-db-table(those are related to a customer-ID and by year, all those data get fetched via a mysql-query). But only some of these accounts shall be used for calculations, not all of them each time.

So my first thought was using the new Fred-extra:

creating different tables as Fred-elements by hand the customer can choose from, and also creating the different accounts off the custom-db-table as Fred-elements by a snippet. So far my snippet worked, I could create a Fred-Element for each account and I created a table by “hand”.

Then I thought the customer might be able to choose the table he wants to use, name all the columns and rows like he wants them to be named (just in case they need to be renamed from the default-values), and just drag’n’drop in each table-cell all the Fred-element accounts he needs to use there. Additionally maybe make an option which kind of math he wants to use (summarize, substract, divide, multiply).

In “Fred-edit-mode” i was able to use a table i created as a Fred-element in the Fred-dropzone, and also drag’n’drop some accounts off the Fred-elements into a table cell. But then I didn’t know how to calculate them. Sure, I could use [[+Account_00100:add=[[+Account_00101:add=[[+Account_00450:add=[[+Account_00800]]]]]]]]
But I don’t want the customer to have to type this by hand, and I guess this might be the worst way to do this. There might be up to 10 or 15 accounts, that should be getting calculated. So there must be a better way to do this.

Then my second approach was to go with the TVs. Create a resource for each table-cell, which has all the available accounts off the custom-db-table as TVs to make them chooseable. Then get all the TVs that have been chosen by the customer with a resource by a snippet and calculate them. Then doing the output by a [[getResource…]]-call, or by creating a placeholder like [[+result_table-cell_XY]].

Another “problem” I haven’t thougt much about yet is bthe ability to use a result of one of the calculations for another calculation in a different table-cell. By thinking of this now I think the placeholders [[+result_table-cell_XY]] I created beforehand by the snippet are usable when the snippet has been run once, but not in the same table/on the same page.

Pretty complex stuff I guess, maybe this is off my limits…

So finally I got back to this topic, trying something new…

I came up with the idea by using MIGX for my task. So I created a new MIGX-TV called “account-config”.

In this MIGX-TV you can enter a “name” (this shall be the name for a placeholder-output later on), the “account”-numbers (comma separated) and an “operator” for choosing math-calculations (addition/sum, subtraction, multiply, multiply with -1).

So I entered two items for testing:

name: Test1
account: 00400,00545
operator: + (sum/addition)

name: Test2
account: 00598,00945
operator: - (substraction)

Next I have a snippet called “get_account_values”. In this snippet I have this call to get all the MIGX-TV-values, that I have entered before:

$val = $modx->resource->getTVValue('account-config');

This outputs me a json-string like that:

[{"MIGX_id":"1","name":"Test1","account":"00400,00545","operator":"+"},{"MIGX_id":"2","name":"Test2","account":"00598,00945","operator":"-"}]

Then I thought it would be helpful to create an array out of the json-string for further use, so I used this:

$json_result = json_decode($val, true);

which outputs this array called “selected_accounts”:

Array
(
    [0] => Array
        (
            [MIGX_id] => 1
            [name] => Test1
            [account] => 00400,00545
            [operator] => +
        )

    [1] => Array
        (
            [MIGX_id] => 2
            [name] => Test2
            [account] => 00598,00945
            [operator] => -
        )

)

So far, so good…

In the same script I’m grabbing data from a db-table with the available accounts and their values. I put the data I need in another array called “all_available_accounts”.

The array looks like this:

Array
(
    [0] => Array
        (
            [account] => 00400
            [value] => 59204.0000
        )

    [1] => Array
        (
            [account] => 00545
            [value] => 406351.0700
        )

    [2] => Array
        (
            [account] => 00598
            [value] => -50177.0300
        )

    [3] => Array
        (
            [account] => 00650
            [value] => 0.0000
        )

    [4] => Array
        (
            [account] => 00945
            [value] => 14418.1200
        )

    [5] => Array
        (
            [account] => 01100
            [value] => -327000.0000
        )
...
)

And this is where I get stuck:

I think I need to check in the array “all_available_accounts” which accounts from the array “selected_accounts” are existing and grab their values.

I am able to achieve this by using another array “test” I created earlier while testing around:

Array
(
    [0] => 00400
    [1] => 00545
)

With this array “test” I grabbed the values out of the array "all_available_accounts with this line:

$only_chosen_accounts = array_intersect_key($all_available_accounts, array_flip($test));

This gives me this output:

Array
(
    [00400] => 59204.0000
    [00545] => 406351.0700
)

Finally I just needed to calculate these values by this:

$sum_only_chosen_accounts = array_sum($only_chosen_accounts );

which outputs the correct calculation:

465555.07

(I havent used the “operator” here so far, which is what I want to add, when the rest of the script runs like I need it to be)

My problem now is how to use this “array_intersect_key”-code on the array “all_available_accounts”.

I guess I need to use a foreach-loop with the array “selected_accounts”, look for the “account”-values that have been entered and do the “array_intersect_key” on the array "all_available_accounts" separately in the loop?

Finally I want to create a placeholder which is called like the “name” that has been entered in the MIGX-TV-items. So the final result of the calculation can be called with [[+Test1]] and the result gets outputted.

I hope this all makes sense, but it “feels” better than my first approach. Any hint will be highly appreciated!

Greetings to the comunity.

Ok, I got it sorted!

Writing down the issue sometimes helps…and sometimes I read in many other forums and a few times the “old MODX-forum” something like “got it/problem solved”, without explaining what they did, which I don’t like…so I want to try to explain my solution…

I’ve got my array " selected_accounts which I run trough a foreach-loop:

 foreach ($selected_accounts as $result) {
    $chosen_accounts = explode(",", $result['account']);

    $only_chosen_accounts = array_intersect_key($all_available_accounts, array_flip($chosen_accounts ));

    $sumAddition = array_sum($only_chosen_accounts );

    $modx->setPlaceholder($result['name'],$sumAddition );
}

This way I can now access the result of the calculation by using the placeholder I set, for exampe [[+Test1]] outputs 465555,07…

I wrote some if-statements regarding the chosen “operator” to do the way of calculation I defined in the MIGX-item.

2 Likes