Meteor tabular tables - multiple tables showing same data - mongodb

I'm using multiple tabular-tables in Meteor to display sets of partitioned data on the same page. Each occurrence of the tabular appears in a separate template instance, but they all refer to the same table. I have a template that looks as follows:
<template name="parentTemplate">
....
{{#each folders}}
{{> childTemplate}}
{{/each}}
....
</template>
<template name="childTemplate">
{{> tabular table=Table class="..." selector=selector}}
</template>
folders returns a set of partitions for the data, selector just returns {folderId: _id}
My Tabular.Table constructor is pretty simple, the only thing of note is:
changeSelector(selector, userId){
const ret = _.extend(selector, {status: "active"});
console.log(JSON.stringify(ret));
return ret;
}
the console.log part returns what I would expect, for each table a different folderId. When I put the logged selector into mongodb, I get the expected partition for each table, however each table shows me the same set of data as the first table. Additionally, when I click "next page" all the tables update to show the partition that should be displayed in the final table. I've checked that all the tabular table elements in the HTML have unique Id's.
Am I just using tabular-tables incorrectly?
EDIT:
After some tinkering, I found a potential solution, but it isn't clean, so I'd still like to hear people's thoughts. What I did was declare a meteor method as follows:
Meteor.methods({Table: function(){return new BlahTable(...);})
This is executed on the client and server, creating the relevant tabular table in both locations, then I use the newly created table in {{>tabular...}}

Related

Select options obtained via ajax and unmap issue

I don't see any examples linking a form using select elements with options obtained via ajax. I am wanting to initialize a view model property via ajax in order to populate some select lists in my view and data-link the selected id from my model data. I don't need these arrays when doing an .unmap() of compiled view model because I don't want to send the large lists back to the server when updating the model. So, let's say I have data with ProjectID, ProjectDescription, ProjectTypeID, ProjectPriorityID. In my view model, I need to get via ajax a list of ProjectTypes and ProjectPriorities and use them in my view so that I can select the value from a list. I'm not sure how to achieve this without getting the lists as part of the data when doing .unmap() to send it back to the server.
If there is a property for "ProjectTypes" or "ProjectPriorites" in my view model, they always become part of the data when calling .unmap().
Thank you
There are different alternative approaches. One is to have a single model that includes both 'secondary data' - such as all the ProjectTypes - which will not change dynamically, and the 'primary data' which can get updated based on user input. In that case when you get plain JSON data back from the VM hierarchy using unmap() you can 'prune' it and send only the relevant 'primary' parts back the server.
Another approach is to keep the primary and secondary data separate - so the model is just the 'primary' data, and the secondary data is separate - for example, passed in as a helper:
// Instantiate View Models
var appVm = $.views.viewModels.MyModel.map(modelData);
var typesVm = $.views.viewModels.MyTypes.map(typeData);
$.templates("#appTemplate").link("#page", appVm, {types: typesVm});
<select data-link="typeId()"><
{^{for ~types.projectTypes()}}
<option value="{{:id()}}">{{:label()}}</option>
{{/for}}
</select>
You can also choose not to compile View Models for the secondary data, if it is basically 'static', and do:
$.templates("#appTemplate").link("#page", appVm, {types: typesData});
<select data-link="typeId()"><
{^{for ~types.projectTypes}}
<option value="{{:id}}">{{:label}}</option>
{{/for}}
</select>
Another approach is to only send back to the server any data values or array that have actually changed, for example by using a CRUD/REST web service approach server updates. In that case you would need to have code that diffs the data, or use observe or observeAll to respond to incremental changes...

How to work with select input with data coming from a simple relational db model

I'm using Angularjs plugged into a API which retrieves data from a mysqlk normal relational db.
Let's say I have this simple data model in my bdd:
table car:
id,
type_id
table type:
id,
label
I have a API which retrieves the data from DB to have the list of cars and the static labels from db:
http://myapi/car/
response :
{[{id:1, type_id:2}, {id:2, type_id:3}]}
http://myapi/carstaticlabel/
response :
{[{id:1, label:convertible}, {id:2, label:limousine}, {id:3, label:pickup}]}
My aim is first to display a list of cars with the type label and then, open a dialog and being able to show a form with preloaded values of the selected car:
rendered list of cars :
1 convertible
2 pickup
rendered form for edited car whose id is 1:
select the type of car:
<select>
<option value="1">convertible</option>
<option value="2" selected="selected">limousine</option>
<option value="3">pickup</option>
</select>
I have tried different approaches but none is elegant
Solution 1
for the list of cars
change my API and make the join directly between car and type to get the list with label:
http://myapi/car/
response :
{[{id:1, type_id:2, type:{[id:2, label:limousine]}}, {id:2, type_id:3, type:{[id:3, label:pickup]}}]}
then I just assign in the form : car.id and car['type']['label']
ISSUE: each car will contain repeated information (label) >> bloated info
for the edit form:
I pass the json of selected car to the form and set default values:
<p>type: <select ng-model="car.type" ng-options="type.label for type in type_list" required></select></p>
MY ISSUE with that:
when I submit the form, I don't get the type_id directly, I get the car.type object instead, so I need to painfully translate it into an id to post into the database.
To convert I have to go into the car.type object and retrieve the object inside and then retrieve its id... very unelegant.
Solution 2
make the "join" inside angular by working with arrays.
ISSUE: very hard to default values in the form later on
I'm lost, what is usually the best practice to achieve that simple task?
You should use select as label for value in array syntax for array data sources. Your example have complex data structure which is array of objects. So you need something like this:
<select ng-model="selectedId"
ng-options="x.id as x.label for x in response">
</select>
I created little example here to demonstrate proposed solution.

Inserting rows in form datasource, insert is OK, rows are not visible

Basically, I want to insert rows in the form InventJournalTransfer. I added a menuitem button that calls a class which opens a dialog where I fill a WMSLocationId, then I loop on Inventsum table to get all ItemIds with Available qty for this WMSLocationId and insert them into InventJournalTrans Table.
The code I wrote seems to be working as I have correct records inserted in my table(visible in Table browser, correct journalId, linenum itemId, qty etc...) BUT the records inserted do not appear in my form. I tried to refresh my form with or without code, but my grid's still empty.
I had a look at the class InventCountCreate that does what I want to do in a different journal type, but as I'm quite a newbie it is difficult for me to understand exactly how this class works.
Could anyone explain to me how to display my inserted rows in my form or give other leads?
The InventJournalTrans is table is inner joined to two InventDim, one related via the InventDimId field, the other via ToInventDimId.
Both fields must be filled with a valid InventDimId to an existing InventDim record for the form to show the record.
Have you tried right-clicking on your form's node in the AOT and clicking "Restore"? Perhaps your form is still using cached data.

How To Process Arbitrary Number of Form Fields

I am using ColdFusion (Railo 3.3), and I have several forms using jQuery that can dynamically add a set of form fields (for instance, the user can tick a box to add another company owner that brings up all the relevant fields for the additional owner). All the information needs to be inserted into a database, but I don't know exactly how many fields will be submitted at any given time.
How do I process this arbitrary number of fields to insert into a DB with ColdFusion?
Thanks!
Form is a structure aka Collection.
You can just loop over the entire form structure and insert all the fields, you will probably need to exclude some like the submit button etc, but you should know the name of this.
<cfloop collection=#form# item="field">
<cfif field neq 'submit'>
.... insert into DB #form[field]#
</cfif>
</cfloop>

APEX - Creating a page with multiple forms linked to multiple related tables... that all submit with one button?

I have two tables in APEX that are linked by their primary key. One table (APEX_MAIN) holds the basic metadata of a document in our system and the other (APEX_DATES) holds important dates related to that document's processing.
For my team I have created a contrl panel where they can interact with all of this data. The issue is that right now they alter the information in APEX_MAIN on a page then they alter APEX_DATES on another. I would really like to be able to have these forms on the same page and submit updates to their respective tables & rows with a single submit button. I have set this up currently using two different regions on the same page but I am getting errors both with the initial fetching of the rows (Which ever row is fetched 2nd seems to work but then the page items in the form that was fetched 1st are empty?) and with submitting (It give some error about information in the DB having been altered since the update request was sent). Can anyone help me?
It is a limitation of the built-in Apex forms that you can only have one automated row fetch process per page, unfortunately. You can have more than one form region per page, but you have to code all the fetch and submit processing yourself if you do (not that difficult really, but you need to take care of optimistic locking etc. yourself too).
Splitting one table's form over several regions is perfectly possible, even using the built-in form functionality, because the region itself is just a layout object, it has no functionality associated with it.
Building forms manually is quite straight-forward but a bit more work.
Items
These should have the source set to "Static Text" rather than database column.
Buttons
You will need button like Create, Apply Changes, Delete that submit the page. These need unique request values so that you know which table is being processed, e.g. CREATE_EMP. You can make the buttons display conditionally, e.g. Create only when PK item is null.
Row Fetch Process
This will be a simple PL/SQL process like:
select ename, job, sal
into :p1_ename, :p1_job, :p1_sal
from emp
where empno = :p1_empno;
It will need to be conditional so that it only fires on entry to the form and not after every page load - otherwise if there are validation errors any edits will be lost. This can be controlled by a hidden item that is initially null but set to a non-null value on page load. Only fetch the row if the hidden item is null.
Submit Process(es)
You could have 3 separate processes for insert, update, delete associated with the buttons, or a single process that looks at the :request value to see what needs doing. Either way the processes will contain simple DML like:
insert into emp (empno, ename, job, sal)
values (:p1_empno, :p1_ename, :p1_job, :p1_sal);
Optimistic Locking
I omitted this above for simplicity, but one thing the built-in forms do for you is handle "optimistic locking" to prevent 2 users updating the same record simultaneously, with one's update overwriting the other's. There are various methods you can use to do this. A common one is to use OWA_OPT_LOCK.CHECKSUM to compare the record as it was when selected with as it is at the point of committing the update.
In fetch process:
select ename, job, sal, owa_opt_lock.checksum('SCOTT','EMP',ROWID)
into :p1_ename, :p1_job, :p1_sal, :p1_checksum
from emp
where empno = :p1_empno;
In submit process for update:
update emp
set job = :p1_job, sal = :p1_sal
where empno = :p1_empno
and owa_opt_lock.checksum('SCOTT','EMP',ROWID) = :p1_checksum;
if sql%rowcount = 0 then
-- handle fact that update failed e.g. raise_application_error
end if;
Another, easier solution for the fetching part is creating a view with all the feilds that you need.
The weak point is it that you later need to alter the "submit" code to insert to the tables that are the source for the view data