Joomla 3.x - How to add & access data attribute in jForm - joomla3.2

For example,
<field name="name" type="text" required="ture" data-attribute-type="Guest" data-attribute-subtype="Guest1"/>
Here I have added data-attribute-type="Guest" and data-attribute-subtype="Guest1" these attributes and assigned values to it. Now I want to access those attributes/values while rendering jForm
<input type="text" name="jform[name]" id="jform_name" required="required" data-attribute-type="Guest" data-attribute-subtype="Guest1" >

You need to access custom attributes via the elements array like this:
Form field (I don't think you want to use data attributes):
<field name="myfieldname" type="myfieldname" required="true" access-type="Guest" access-subtype="Guest1"/>
Then you need to define a custom Field and do your magic (probably in render or renderField:
class JFormFieldMyFieldName extends JFormField
{
public function renderField($options = array())
{
$access_type = $this->element['access_type']);
$access_subtype = $this->element['access_subtype']);
// do whatever
}
}
This is all untested but hopefully gets you moving in the right direction.

Related

How can I pass value as GET through a hyperlink?

I have two entities - Budget and Income. On the "view budget" page I have this hyperlink, from where the user can create an income to that specific budget:
Create income to this budget
// Result: /income/new?budget=1
// What I want: /income/new
Is it possible somehow to remove ?budget=1 and still pass on the budget.id as a POST variable value so the hyperlink becomes short: /income/new?
You cant pass post parameters with an anchor
You could use a form though, sth like:
<form action="{{ path('app_income_new') }}" method="POST">
<input type="hidden" name="budget" value="{{ budget.id }}">
<input type="submit" value="Create income to this budget">
</form>
should do the trick, maybe add some css to make it "look like a link"
In order to have this behavior with just an actual anchor <a> element you need to use a javascript event listener to build and submit a form element when the anchor is clicked. You can insert the related data (path & budget.id) into data attributes of the anchor. The event listener can access the data of the clicked anchor (so you can have many with different datasets). Below is a configurable example that can support additional fields by adding the field name where noted, and the appropriate data attribute.
const postAnchors = document.querySelectorAll(".post-link");
postAnchors.forEach((anchor) => {
anchor.addEventListener('click', function(e) {
const fields = [
'budget',
// to support additional fields add here
]
const form = document.createElement('form')
fields.forEach(field => {
if (anchor.dataset[field]) {
const input = document.createElement('input')
input.name = field
input.type = 'text'
input.value = anchor.dataset[field] // data-{field} value
form.append(input)
}
})
form.method = 'post'
form.action = anchor.dataset.action
document.querySelector('body').append(form)
form.submit()
})
})
Create income to this budget

Redux forms render fields based on prop values

I am creating a form using redux-forms (v7.4.2). I am trying to conditionally render a field based on PROP values. To be clear, I am NOT trying to conditionally render a field based on the inpit of another field in the form. I want redux-forms to look at a prop value and render a field one-way or another base on the value of that props.
I tried the code below but it just shows both fields. The props are present (I can see them using react dev tools). Basically, what I'm aiming to do here is to look and see if a prop exisits. If the length of that array is > 0 then a user is edititng the form and I want to disable this field. Otherwise, if length === 0 then its a new record and the field is required.
{this.props.facilityCompliance.length === 0 ?
<Field
label="Facility Name"
name="facilityName"
placeholder="Facility Name"
component={renderInputField}
type="text"
validate={required}
/>
:
<Field
label="Facility Name"
name="facilityName"
placeholder="Facility Name"
component={renderInputField}
type="text"
disabled={true}
/>}

Thymeleaf: handling maybe-existing properties of a model?

Problem:
I have a Thymeleaf template in Spring MVC which I want to use for two things:
1) For creating a new entity in the database
2) For updating an existing entity in the database
There is only one tiny difference between those two use cases: The entity in the database has a version (optimistic locking) attribute set, so I want to remember this version as a hidden field in the template, which is easy to do.
To understand better where i am coming from here is my handler code for creating a new entity:
#GetMapping("/new")
String showMapFormForAdd( Model model ) {
model.addAttribute( "map", null ); // PASS null into it
return "map-form"; // same template
}
And here is the code for updating an existing entity:
#GetMapping("/{mapId}/update")
public String showMapFormForUpdate( #PathVariable Long mapId, Model model ) {
GameMap map = mapService.findMap( mapId );
model.addAttribute( "map", map ); // PASS the real map into it (with version!!!)
return "map-form"; // same template
}
And here is the code for the hidden version field in the Thymeleaf template:
<input type="hidden" th:value="${map?.version}" name="version" />
However, when the template is rendered after the first handler (creating), I get an Exception, that the property version does not exist (its true, it doesn't exist).
Question:
How can I tell Thymeleaf, to only query the version and set it to value in the hidden field, only if the property version does exist in the "map" model which is injected into Thymeleaf?
You can add conditional th:value
<input type="hidden" th:value="${map.version != null ? map.version : ''}" name="version" />

use the same form for create and read operation

I have a master and a child component. The child component persists the data for the create mode as well as the edit mode. The child has a data section as follows which is being used when the component is in create mode
data() {
return {
title: '',
description: '',
organizer: '',
startdate: '',
enddate: '',
email: '',
phone: ''
}
},
and my inputs in create mode are as follows
<input type="text" placeholder="enter event title here" class="form-control" v-model="title">
In the edit mode, I am updating a prop value on the client as follows, which is
props:['currentevent']
The value of the currentevent is being passed from the master component to the child component and is also the value that is currently being edited.
so, the complete code for handling an input value looks like as follows
<input type="text" placeholder="enter event title here" class="form-control" v-if="currentevent" :value="currentevent.title">
<input type="text" placeholder="enter event title here" class="form-control" v-else v-model="title">
and in my save method (in the child component), I am checking if currentevent is empty or not. If it is empty then I trigger the add code otherwise, I trigger the update code.
Question : This works , but I have a large form and having to do this for each and every component is not a clean design . Can you please let me know what should I be doing ?
I totally appreciate your predicament. The best way to handle form data is to make it create/update agnostic. Here's what I'd recommend you try:
Instead of maintaining all the data fields as disparate properties, contain them in a single object, in this case I'm calling it eventObj for clarity:
data () {
return {
eventObj: {}
}
}
Then in your markup you'd reference them via the object:
<input type="text" placeholder="..." class="form-control" v-model="eventObj.title">
You'd then need to define a prop for passing in the data (as an object) from the parent component if you are editing:
props: {
currentevent: Object
}
And then you'd just need to map the incoming prop to the child component's data:
created() {
Object.assign(this.eventObj, this.currentevent || {})
}
Now when your inputs like <input v-model="eventObj.title"> are processed, if there is a saved title (that was passed in with currentevent) the field will be prepopulated with it, otherwise it will be blank.
I think this should help you in the right direction toward solving the complexity you're trying to figure out. There are other logistical issues involved with this kind of stuff in general, but I won't drone on. :)
The issue I see is you want to remove the v-if/else in the form. I will recommend here is keep your local data of child to be in sync with the props passed and only use local variable in the form.
One way to do this can be put a watcher on props and whenever props changes, update local variables and only use those variables in form.
watch: {
currentevent: function(newVal){
title = newVal.title,\
description = newVal.description
...
}
}

Meteor, how to submit an array of forms

I have a Meteor application where I want to describe a "site" and a number of "ios" (input/outputs) for each site. The site is described by the first 3 fields and stored in a collection named sites. The ios are entered below that, and are stored in a collection named ios. The idea is each site may have an arbitrary number of ios. I would like to be able to edit any field for the site or any of the ios, click save, and have everything saved at once. Because the number of ios will be limited to say 5 or so by physical circumstances, I think this will be a better user experience than having a separate edit page for ios. However, I can't figure out how to save the ios when the site form is saved. How could this be implemented?
Here is an image of what the form looks like:
https://app.box.com/s/rqjj9lb49twcitwo7rmdy6k9ta0vuztv
Assuming a structure like this:
<template name="form">
<form name="form">
<input type="text" name="foo" />
<input type="text" name="bar" />
<button type="submit">Submit Form</button>
</form>
</template>
Some code like this will add your different elements to different collections:
Template.form.events({
'submit form[name="form"]': function(e) {
var foo, bar, fooInsert, barInsert;
e.preventDefault();
foo = $(e.target).find('[name="foo"]').val();
bar = $(e.target).find('[name="bar"]').val();
fooInsert = {
thing: foo
}
barInsert = {
thing: bar
}
fooInsert._id = Collection1.insert(fooInsert); // Insert foo into Collection1
barInsert._id = Collection2.insert(barInsert); // Insert bar into a different collection, Collection2
}
});
It would help if you did show some code you're working with so we can make our answers better :)

Resources