How can I pass value as GET through a hyperlink? - symfony

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

Related

Custom ui:widget will not alter the formData

When using ui:widget the field will not change the formData of the form, unlike when not using ui:widget any change in the field will be seen in the formData when the form is submitted.
Shall I change the formData of the form manually when the field text changes? if so, is there an example to do so?
Steps to Reproduce
Create the class that represent the custom UI, and use the following for render:
return (
<div >
{this.props.children}
</div>
)
Add to the schema.properties "City": {type: "string", title:"City"}
Add to the schema.properties "City": { "ui:widget": DefaultInput, classNames: "col-md-4"}
Where City is the name of the custom component.
and DefaultInput is the class that represent the custom ui of field.
Expected behavior
To see the value of the custom text field when submit the form:
onSubmit = ({formData}) => console.log(formData);
What I see is:
{City: undefined}
Any idea?
if you use custom 'ui:widgets' you have to use the json-schema-form onChange method when any item's value gets changed and after that you can get changed value from form.

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
...
}
}

creating element on click in Meteor

I'm using Meteor with React. I have a really simple goal, but i have tried a lot and can't solve it for myself. I will show you my attemps below.
I want to create a form for the Ingredients. At the first moment there is only one input (for only one ingredient) and 2 buttons: Add Ingredient and Submit.
class IngredientForm extends Component {
render() {
return(
<form onSubmit={this.handleSubmit.bind(this)}>
<input type="text"/>
{ this.renderOtherInputs() }
<input type="button" value="Add Ingredient" onClick={this.addIngredient.bind(this)}>
<input type="submit" value="Submit Form">
</form>
);
}
}
So when I click Submit then all the data goes to the collection. When I click Add Ingredient then the another text input appears (in the place where renderOtherInputs() ).
I know, that Meteor is reactive - so no need to render something directly. I should underlie on the reactive data storage.
And I know from the tutorials the only one way to render something - I should have an array (that was based on collection, which is always reactive) and then render something for each element of that array.
So I should have an array with number of elements = number of additional inputs. that is local, so I can't use Collection, let's use Reactive Var instead of it.
numOfIngredients = new ReactiveVar([]);
And when I click Add button - the new element should be pushed to this array:
addIngredient(e) {
e.preventDefault();
let newNumOfIngredients = numOfIngredients.get();
newNumOfIngredients.push('lalal');
numOfIngredients.set(newNumOfIngredients);
}
And after all I should render additional inputs (on the assumption of how many elements I have in the array):
renderOtherInputs() {
return numOfIngredients.get().map((elem) => {
return(
<input type="text"/>
);
}
}
The idea is: when I click Add button then new element is pushed to the ReactiveVar (newNumOfIngredients). In the html code I call this.renderOtherInputs(), which return html for the as many inputs as elements I have in my ReactiveVar (newNumOfIngredients). newNumOfIngredients is a reactive storage of data - so when I push element to it, all things that depends on it should re-render. I have no idea why that is not working and how to do this.
Thank you for your help.
Finally I got the solution. But why you guys don't help newbie in web? It is really simple question for experienced developers. I read that meteor and especially react have powerful communities, but...
the answer is: we should use state!
first let's define our state object in the constructor of react component:
constructor(props) {
super(props);
this.state = {
inputs: [],
}
}
then we need a function to render inputs underlying our state.inputs:
renderOtherInputs() {
return this.state.inputs.map( (each, index) => {
return (
<input key={ index } type="text" />
);
});
}
and to add an input:
addInput(e) {
e.preventDefault();
var temp = this.state.inputs;
temp.push('no matter');
this.setState({
inputs: temp,
});
}
p.s. and to delete each input:
deleteIngredient(e) {
e.preventDefault();
let index = e.target.getAttribute('id');
let temp = this.state.inputs;
delete temp[index];
this.setState({
inputs: temp,
});
}

Select2 Posting Ids instead of text

I am initializing select2(multiple) with remote data (json) and when the form is submitted select2 submits the indexes of the selected text(s), can it return selected text(in comma separated like indexes) instead of indexes?
<input type="hidden" id="IntendedCourses" name="IntendedCourses"/>
$.getJSON("GetCourses.aspx", function (course) {
$("#IntendedCourses").select2({
multiple: true,
data: course
});
});
json format :
[{"id":"0","text":"Accounting"},{"id":"1","text":"Accounting & Finance"},{"id":"2","text":"Aeronautical"},{"id":"3","text":"Aerospace Engineering"}]
I believe what you need is:
$("#IntendedCourses").change(function() {
var selection = (JSON.Stringify($("#IntendedCourses").select2('data')));
});
This should give you the JSON for what is inside the selection upon change.

Stay in same location on submit the form

When i submitting the form the page will navigate to starting of page.
i want to stay on same location. is there any method to do that?
Yes, instead of using the form submission, send an asynchronous request in JavaScript using XHR. To give a concrete example, suppose you have a simple form that looks like:
<form method="POST" action="/path/to/submit">
<input id="input_name" name="input_name" type="text" value="value" />
</form>
Using XHR, it might look something like the following (using the Closure library for XHR):
<script>
goog.require('goog.net.XhrIo');
var submitCompleted = function() {
alert('Submitted!');
};
var submitAction = function() {
var value = document.getElementById('input_name').value;
goog.net.XhrIo.send(
'/path/to/submit',
submitCompleted,
'POST',
'input_name=' + encodeURIComponent(value));
};
</script>
I'm assuming that you still keep the same input element as before, but that you define your onsubmit function to invoke submitAction instead of using the default submission behavior of your form.

Resources