Powermail: create fields from entries in database - typo3

My problem:
i need a matrix of fields in Powermail:
product_1 - price_1 - number_1
product_2 - price_2 - number_2
product_3 - price_3 - number_3
and so on. No problem to create this fields manually, but i need it derived from a database. The numbers of lines depends on the number of entries in the database.
is there a possibility to create fields "on the fly", perhaps by typoscript or a userfunc?
Thanks!

I would create a new field type an call it (e.g.) productsheet. In the manual there is an example how to do it: https://docs.typo3.org/typo3cms/extensions/powermail/ForDevelopers/AddNewFields/Index.html
Here two example page TSConfig lines for the new field:
# Add new fields
tx_powermail.flexForm.type.addFieldOptions.productsheet = Product Fields
tx_powermail.flexForm.type.addFieldOptions.productsheet.dataType = 1
Here is an example Productsheet.html partial file for this:
{namespace vh=In2code\Powermail\ViewHelpers}
<h2><vh:string.escapeLabels>{field.title}</vh:string.escapeLabels><f:if condition="{field.mandatory}"><span class="mandatory">*</span></f:if></h2>
<table>
<thead>
<tr>
<th scope="col">Menge</th>
<th scope="col">Artikel Nr.</th>
<th scope="col">Bezeichnung</th>
<th scope="col">Preis Fr./m</th>
</tr>
</thead>
<tbody>
<f:for each="{0:1,1:2,2:3,3:4,4:5,5:6,6:7,7:8,8:9,9:10}" as="key">
<tr>
<td>
<f:form.textfield type="number" class="mdl-textfield__input " name="field[{field.marker}][amount_{key}]" value="" />
</td>
<td>
<f:form.textfield class="mdl-textfield__input " name="field[{field.marker}][article_no_{key}]" value="" />
</td>
<td>
<f:form.textfield class="mdl-textfield__input " name="field[{field.marker}][description_{key}]" value="" />
</td>
<td>
<f:form.textfield class="mdl-textfield__input " name="field[{field.marker}][price_{key}]" value="" />
</td>
</tr>
</f:for>
</tbody>
</table>
Next step would be to insert fields - as you wrote - on the fly. So what about inserting an own viewhelper instead of defining a hardcoded array in the
Now you could prefill the fields with value="" by your own.
Hope that helps

You can use the TypoScript field of powermail to generate code from typoscript.
You can also use your own field type like discribed here with page TSConfig:
tx_powermail.flexForm.type.addFieldOptions.new = New Field
# The label could also be written with LLL: to localize the label
# Example to grab a value from locallang.xml or locallang.xlf
#tx_powermail.flexForm.type.addFieldOptions.new = LLL:EXT:ext/Resources/Private/Language/locallang.xlf:label
# Tell powermail that the new fieldtype will transmit anything else then a string (0:string, 1:array, 2:date, 3:file)
# Example for dataType array
#tx_powermail.flexForm.type.addFieldOptions.new.dataType = 1
# The new field is not just a "show some text" field. It's a field where the user can send values and powermail stores the values?
# You can tell powermail that this new field should be exportable in backend module and via CommandController
#tx_powermail.flexForm.type.addFieldOptions.new.export = 1
newis the field identifier. Powermail search by default for a partial with the identifier name e.g. New.html.
Now you can use a ViewHelper to get the data and create the html for the fields.

Related

Accordion Bootstrap table with spacebars

I have seen questions pertaining to accordion but not entirely to my specific need. My table is populated using spacebars, more specific a nested each loop like this:
<tbody>
{{#each piece in pieces}}
<tr id="{{piece._id}}" class="itemList table-warning">
<th class="name tText">{{piece.name}} {{piece._id}}</th>
<td class="pdf tText" style="text-align: center"><a class ="pdf" href="{{piece.pdf}}" target="_blank"><i class="fa fa-file-text-o" aria-hidden="true"></i></a></td>
<td class="audio tText" style="text-align: center"><a class="audio" href="{{piece.audio}}" target="_blank"><i class="fa fa-volume-up" aria-hidden="true"></i></a></td>
<td class="format tText">{{piece.instrumentation}}</td>
<th class="price tText" >${{piece.price}}</th>
<td><input class ="qty" type ="number" name ="quantity" value="0" min="0"></td>
</tr>
<!-- Row that is being clicked-->
<tr class="partsList">
<td colspan="3"></td>
<th class="partName tText">{{piece.name}} Parts</th>
<td colspan="2"></td>
</tr>
{{#each part in piece.parts}}
<!-- Rows that should accordion -->
<!-- Currently ALL rows accordion on click. Need to accordion based on _id-->
<tr class="partList">
<td colspan="3"></td>
<td class="pname tText">{{piece.name}}: {{part.pname}}</td>
<td class="price tText">${{part.pprice}}</td>
<td><input class="qty" type="number" name="quantity" value="0" min="0"></td>
</tr>
{{/each}}
{{/each}}
</tbody>
I have a click function like so:
'click .partsList': function(e){
e.preventDefault();
$('.partList').nextUntil('tr.itemList').toggle();
}
The accordion function works, however it works with every instance of the each loop. i.e. every tr class ="partsList" will accordion at the same time on click.
To my understanding of the each loop, I can access the _id of a document using {{piece._id}}. If I set the table row id to equal that however, it only reads the _id of the FIRST document in the collection.
What I need is on click for the <tr class="partList"> to accordion based on _id. Or perhaps you would go about this a different way than bootstrap tables?
Please let me know if my question needs clarification.
You could filter the clicked .partslist using a data-* attribute. This causes jQuery to select only this specific items. Note that you need to attach the data-* attribute to the row that is clicked and to the rows that should collapse:
<tbody>
{{#each piece in pieces}}
...
<!-- Row that is being clicked-->
<!-- use the _id value of the piece context as data attribute -->
<tr class="partsList" data-id="{{piece._id}}">
<td colspan="3"></td>
<th class="partName tText">{{piece.name}} Parts</th>
<td colspan="2"></td>
</tr>
{{#each part in piece.parts}}
<!-- Rows that should accordion -->
<!-- Currently ALL rows accordion on click. Need to accordion based on _id-->
<!-- use the _id value of the piece context as data attribute -->
<tr class="partList" data-target="{{piece._id}}">
...
</tr>
{{/each}}
{{/each}}
</tbody>
'click .partsList': function(e, templateInstance){
e.preventDefault();
// get the data-id attribute of the clicked row
const targetId = templateInstance.$(e.currentTarget).data('id')
// skip if this row is not intended to toggle
if (!targetId) return
// toggle based on data-target attribute
templateInstance.$(`.partList[data-target="${targetId}"]`).nextUntil('tr.itemList').toggle();
}

web2py: multiple forms on one page

I am trying to make a form which shows all products from a group in a list. They can be given a quantity and added to a quote. Which is then stored in the database.
None of the automagical form options are working for me. So I've made each row showing information for a given product with the Quantity box and an add item button it's own form. But the loop which makes each form is doing something strange.
Controller:
products = db(db.product.group_id == productgroupnumber).select()
forms=[]
for product in products:
form = FORM(TABLE(TR(TD(product.productname),
TD((product.purchasecost or 0)),
TD((product.monthlycost or 0)),
TD(INPUT(_type='number', _name='quantity')),
TD(INPUT(_type='submit', _value=T('Add to Offer')))
)
)
)
forms.append(form)
session.quotedproducts = []
if form.accepts(request, session, keepvalues = True):
product = db(db.product.id == product_id).select().first()
offeritem = [product_id, request.vars.quantity, product.purchasecost, product.monthlycost]
session.quotedproducts.append(offeritem)
response.flash = T("Item added to offer")`
For 2 rows. The View has the below 2 forms, with only one hidden div with the formkey and formname. So I can't name the forms in order to process them properly:
<form action="#" enctype="multipart/form-data" method="post">
<table>
<tr>
<td>Block of 10 Phone Numbers</td>
<td>19.0</td>
<td>0</td>
<td><input name="quantity" type="number" /></td>
<td><input type="submit" value="Add to Offer" /></td>
</tr>
</table>
</form>
<form action="#" enctype="multipart/form-data" method="post">
<table>
<tr>
<td>100 Block of Phone Numbers</td>
<td>149.0</td>
<td>0</td>
<td><input name="quantity" type="number" /></td>
<td><input type="submit" value="Add to Offer" /></td>
</tr>
</table>
<!--Why is there only one of these??-->
<div style="display:none;">
<input name="_formkey" type="hidden" value="b99bea37-f107-47f0-9b1b-9033c15e1193" />
<input name="_formname" type="hidden" value="default" />
</div>
</form>
How do I give the forms individual names (preferably product.id)?
I tried adding the formname argument:
form.accepts(request, session, formname=product.id)
But this only names one form and the other is still named 'Default'.
In your code, you create multiple forms in the for loop, but after exiting the loop, you call form.accepts(). At that point, the value of form is the last form created in the loop, so only that form is processed.
Note, when a form is initially created, the form.accepts (or the preferred form.process) method adds the _formname and _formkey hidden fields to the form (these are used for CSRF protection). When that same method is called after form submission, it additionally handles form validation. So, given your workflow, you must process all the forms both at creation and submission. Maybe something like this:
products = db(db.product.group_id == productgroupnumber).select()
forms = []
for product in products:
quantity_name = 'quantity_%s' % product.id
form = FORM(TABLE(TR(TD(product.productname),
TD((product.purchasecost or 0)),
TD((product.monthlycost or 0)),
TD(INPUT(_type='number', _name=quantity_name)),
TD(INPUT(_type='submit', _value=T('Add to Offer')))
)
)
)
if form.process(formname=product.id, keepvalues=True).accepted:
offeritem = [product.id, form.vars[quantity_name],
product.purchasecost, product.monthlycost]
session.quotedproducts.append(offeritem)
response.flash = T("Item added to offer")
forms.append(form)

How to delete specific table data from a table?

In my application I've a table with 40 rows. How do I delete some specific <td> named as "default", "tags", "city", "organic" in that table? All the deletes links are images with the same src name. Please find the attachment of the table row.
My step def:
Then(/^I click on all the delete rules on the setup page$/) do
words = ["default", "tags","organic","city"]
#current_page.delete_rules(:words => words)
end
In my ruby class I've added delete_rules method as below:
def delete_rules(words)
image_elements(:src => "/tracker/images/skin2/bin.png").click
end
Problem here is its deleting the first row in the table, not the rows which I've mentioned in the array.
My HTML is:
<tr>
<td>
tags
</td>
<td>
<a href="delete.page?did=83">
<img title="Delete" src="/tracker/images/skin2/bin.png">
</a>
<a href="edit.page?id=83">
<a href="activate.page?id=83">
</td>
<td>
</td>
you should use the following code in your delete method:
#check all <tr>
#browser.trs.each do |row|
# the row below will check the first <td> text in order to find "default", "tags", "city","organic"
if row.text.match(/default|tags|organic|city/)!= nil
# the row below will click the 1st link in the 2nd <td>
row.td(:index=>1).link.click
end
end

Watir webdriver - How to click on dynamically generated last <td> in table?

In my application,I've to select the last td (which is an img) in table.Can anyone help me with this ?
HTML
<table>
<tbody>
<tr>
<td>
<td>
<a onclick="return confirm('Delete creative?')" href="delete.page?cid=47">
<a href="edit.page?id=47"><a href="?duplicateId=47">
<img title="Duplicate" src="/tracker/images/skin2/bolean.png">
</a>
</td>
</tr>
</tbody>
</table>
Implemenetd as below :
#browser.img(:src => "/tracker/images/skin2/bolean.png").click
#browser.img(:src => "/tracker/images/skin2/bolean.png").last.click
which is clicking on the first image.
When you do:
#browser.img(:src => "/tracker/images/skin2/bolean.png")
This returns the first matching element.
If you want to get all of the matching elements, you need to pluralize the method:
#browser.imgs(:src => "/tracker/images/skin2/bolean.png")
You will then get a collection of all images that have the specified src. You can then get the last one and click it similar to how Ċ½eljko did it for tds.
#browser.imgs(:src => "/tracker/images/skin2/bolean.png").last.click
Try this:
#browser.tds.last.click

jQuery Selecting multiple, different-type, elements in td

Given this table structure:
<table id="tblBranchDetails">
<tr>
<td width="120px">Branch:</td>
<td id="branchName" class="branchData">
<label id="lblBranchName"></label>
<input type="text" id="txtBranchName" class="hideOnLoad editBranchInfo" />
</td>
</tr>
<tr>
<td>Address Line 1:</td>
<td id="branchAddress1" class="branchData">
<label id="lblAddress1"></label>
<input type="text" id="txtAddress1" class="hideOnLoad editBranchInfo" />
</td>
</tr>...
I'm trying to select the label and input in each td so I can clear the label's text and hide the input.
This gives me the text in the label (verified in the console):
$('table#tblBranchDetails tr td:nth-child(2):eq(0)').text();
So I know I can clear the label's text with ".text('')"
Having figured that out, I thought this would give me the value of the input:
$('table#tblBranchDetails tr td:nth-child(2):eq(1)').val()
But it gives me the value of the label in the next td. So obviously I'm using the :nth-child() and :eq() functions wrong.
What's the correct way to do what I'm trying to do?
I was nuking this.
Here's the solution:
$('#btnShowBranchEditBoxes').click(function() {
$('#tblBranchDetails tr').find('label').fadeOut(200);
$('#tblBranchDetails tr').find('.editBranchInfo').delay(200).fadeIn(200);
// Replace the buttons
$('table#tblBranchDetails input#btnShowBranchEditBoxes').fadeOut(200);
$('table#tblBranchDetails input.btnEditBranch').delay(200).fadeIn(200);
});