I am using tagsinput for some tagging operation. I want to add some default value to the tag field that is sent from controller. But it seems that the way i am trying to use the js expression is not working. Can anyone help me. Here is code.
<script>
var cities = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('text'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
local: members
});
cities.initialize();
var elt = $('#researcher');
elt.tagsinput({
itemValue: 'value',
itemText: 'text',
allowDuplicates: false,
typeaheadjs: {
name: 'cities',
displayKey: 'text',
source: cities.ttAdapter()
}
});
#foreach ($memberResearch->member as $member)
{!! $text = $member->firstName." ".$member->lastName !!}
{!! $id = $member->member_id !!}
#if($member->pivot->role == "Researcher")
elt.tagsinput('add' , {"value" : {{ $id }} , "text" :{{ $text }} });
#endif
#endforeach
</script>
PHP and Javascript are two very seperate entities.
For this kind of stuff, the best approach is for laravel to dump the contents (the data) into the page somewhere where the frontend (javascript) can then pick up.
For example:
// controller
$appConfig = [ 'foo' => 'bar' ];
// blade
<script>
var AppConfig = {!! ! empty($appConfig) ? json_encode($appConfig) : "{}" !!};
</script>
// js
var foo = JSON.parse(AppConfig).foo;
console.log(foo); // outputs bar
Related
i am actually using graphs in my project for which i am passing dynamic data from controller to blade and then in the js script. The js function in the blade accept the array of objects and i dont know how to assign the data from the controller to that js function.
$data['typesBasedProperties'] = DB::table('properties')
->join('property_types', 'properties.property_type', 'property_types.id')
->select('property_types.types as label', DB::Raw('COUNT(properties.id) as value'))
->whereIn('properties.id', $property_ids)
->groupBy('label')
->get()
->toJson();
and this is the js function
var donutChart = function(){
Morris.Donut({
element: 'morris_donught',
data: [
{
label: " Download Sales ",
value: 12,
}, {
label: " In-Store Sales ",
value: 30
}, {
label: " Mail-Order Sales ",
value: 20
}
],
resize: true,
redraw: true,
colors: ['#2b98d6', 'rgb(59, 76, 184)', '#37d159'],
//responsive:true,
});
}
I think you need to do something like this:
<script>
var typesBasedProperties = {!! $typesBasedProperties !!}
</script>
After this you have typesBasedProperties object available in all your js code.
Check out laravel documentation for more info.
You can use ajax request to fetch data from laravel controller to javascript or JQuery.
here's some example
controller
function bbq(Request $r){
$data = DB::select('CALL bukubesar('.$r->no.')');
$node = DB::select('CALL infonode('.$r->no.')');
return array(
'data' => $data,
'node' => $node
);
}
route (I'm using Group)
Route::controller(CPembukuan::class)->group(function () {
Route::get ('/pembukuan-besar', 'bukubesar');
Route::get ('/pembukuan-besar/query', 'bbq' );
Route::get ('/pembukuan-labarugi', 'labarugi' );
Route::get ('/pembukuan-labarugi/query', 'lrq' );
});
ajax (JQuery) on html or blade file
//a variable to pass to controller (optional)
val = $('#kode').val();
$.ajax({
type: "get",
url: "/pembukuan-besar/query",
data: {
'no': val // the data represented as 'no'
},
success: function(data) {
console.log(data); // to view the data in console
//do anything you want here
}
});
I am trying to make a form that changes based on user response, I have a ChoiceType::class for the first part with 'yes' or 'no' as the options. If the user selects 'yes' I want the second part of the form to show up to get their response to that, but if they select 'no' I just want to keep that second form hidden.
This is the form I have so far
public function buildForm(FormBuilderInterface $builder, array $options)
{
->add('attending', ChoiceType::class, [
'choices' => [
'yes' => true,
'no' => false,
],
'attr' => [
'class' => 'attendanceStatus'
],
'mapped' => false,
'required' => true,
'label' => 'Will you be attending?',
'placeholder' => 'Please make selection',
])
->add('bringingGuest', ChoiceType::class, [
'choices' => [
'yes' => true,
'no' => false,
],
I wrapped the forms in a class and gave each form an ID
<div class="attendance">
<div id="attendance-status">
{{ form_label(form.attending) }}
{{ form_errors(form.attending) }}
{{ form_widget(form.attending) }}
</div>
<div id="guest" style="display: none;">
{{ form_label(form.bringingGuest) }}
{{ form_errors(form.bringingGuest) }}
{{ form_widget(form.bringingGuest) }}
</div>
</div>
I'm not the greatest with javascript but I tried to do an if statement like this
if ('.attending' == true) {
document.getElementById('guest').style.display = 'block';
}
I've been at this for a bit of time now and I can't seem to figure out how to do it properly. I thought it would be something like having an event listener for the user selection and then just using javascript to show the second form if conditions are met.
This is, like you probably already know, a javascript question. Like you said, you can use an event listener, for example to run a function whenever a value changes. Here's an example:
const someId = document.getElementById('some-id');
const example = document.getElementById('example');
someId.addEventListener('change', doSomething);
function doSomething() {
if (someId.value === "yes") {
example.innerHTML = "YES!"
} else {
example.innerHTML = ""
}
}
<select name="name" id="some-id">
<option value="no">no</option>
<option value="yes">yes</option>
</select>
<div id="example">
</div>
All you need to do is check what IDs you should target and what you want to happen on which event. To find out more about events, see: https://developer.mozilla.org/en-US/docs/Web/Events.
You may want to check How to Dynamically Modify Forms Using Form Events page in Symfony docs.
In your case it will be Dynamic Generation for Submitted Forms section.
It involves 2 types of events - Form events on PHP/Symfony side and JS mostly "passive" role to listen for element change and replace the HTML.
The idea is next:
On user action on the HTML element send a request to backend and render the new state for the page based on the element's changed value. Here you get full page HTML as a response.
Then just replace dependent chunks of the page with the new rendered pieces of HTML you get from the response.
Here are main parts (copy-pasted from the docs):
// src/Form/Type/SportMeetupType.php
namespace App\Form\Type;
use App\Entity\Position;
use App\Entity\Sport;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormInterface;
// ...
class SportMeetupType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('sport', EntityType::class, [
'class' => Sport::class,
'placeholder' => '',
])
;
$formModifier = function (FormInterface $form, Sport $sport = null) {
$positions = null === $sport ? [] : $sport->getAvailablePositions();
$form->add('position', EntityType::class, [
'class' => Position::class,
'placeholder' => '',
'choices' => $positions,
]);
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
// this would be your entity, i.e. SportMeetup
$data = $event->getData();
$formModifier($event->getForm(), $data->getSport());
}
);
$builder->get('sport')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
// It's important here to fetch $event->getForm()->getData(), as
// $event->getData() will get you the client data (that is, the ID)
$sport = $event->getForm()->getData();
// since we've added the listener to the child, we'll have to pass on
// the parent to the callback functions!
$formModifier($event->getForm()->getParent(), $sport);
}
);
}
// ...
}
in JS:
{# templates/meetup/create.html.twig #}
{{ form_start(form) }}
{{ form_row(form.sport) }} {# <select id="meetup_sport" ... #}
{{ form_row(form.position) }} {# <select id="meetup_position" ... #}
{# ... #}
{{ form_end(form) }}
<script>
var $sport = $('#meetup_sport');
// When sport gets selected ...
$sport.change(function() {
// ... retrieve the corresponding form.
var $form = $(this).closest('form');
// Simulate form data, but only include the selected sport value.
var data = {};
data[$sport.attr('name')] = $sport.val();
// Submit data via AJAX to the form's action path.
$.ajax({
url : $form.attr('action'),
type: $form.attr('method'),
data : data,
success: function(html) {
// Replace current position field ...
$('#meetup_position').replaceWith(
// ... with the returned one from the AJAX response.
$(html).find('#meetup_position')
);
// Position field now displays the appropriate positions.
}
});
});
</script>
I'm trying to get the selected value from a Form::select in a blade's javascript file.
This is my blade:
{!!Form::open(['route' => [$complete == true ? 'completeAnalytical.store' : 'analytical.store'], 'method' => 'POST', 'id' => 'multiparametricAnalyticalForm'])!!}
{!! Form::select('fluid_type',['1' => 'Oil', '2' => 'Gas'], null, ['class'=>'form-control', 'id' => 'fluid_type']) !!}
{!! Form::submit('Run' , array('class' => 'btn btn-primary', 'id' => 'save')) !!}
This is the JS of my blade:
function myFunction() {
var myVar = $("input[name = fluid_type]").val();
console.log(myVar);
}
This is the console answer:
undefined
Is there any way to get the selected value ?
Thanks so much for the help!
You may want to select the element by the id you've set for it.
Change the selector to
$("#fluid_type").val()
With your code
function myFunction() {
var myVar = $("#fluid_type").val();
console.log(myVar);
}
More information
Say I have a controller like this:
public function showAction(Request $request, $id, $context = array())
{
$url = $this->getPlayUrl($id, $context);
//some code here}
I want to use the variable $url in a frontend js file like this :
var html = '<iframe src=\''+ url +'\' name=\'viewerIframe\' id=\'viewerIframe\' width=\'100%\'allowfullscreen webkitallowfullscreen height=\'100%\' style=\'border:0px\'></iframe>';
How am I supposed to make this happen? For the code above ,it gave me 'undefined url' error.
Thank you.
Another option would be to have your template call a controller action (so you can pass parameters as required), for example, like this example for using highchart.js:
{% block javascripts %}
{{ parent() }}
<script src="/js/highcharts.js"></script>
<script src="/js/exporting.js"></script>
<script type="text/javascript">
{{ render(controller('AppBundle:Default:script')) }}
</script>
{% endblock %}
In the controller it looks like this:
public function scriptAction() {
$reports = $this->get('app.reports');
$chart = $reports->getDistsFYToDate();
return $this->render('Default/script.js.twig', array(
'chart' => $chart,
));
}
and script.js.twig looks like this:
$(document).ready(function () {
var options = {
chart: {
type: 'line'
},
title: {
text: 'Distributions, FY{{ chart.fy }} to date'
},
xAxis: {
categories: [{% for category in chart.categories %}{{category|raw}}{%endfor%}]
},
yAxis: {
title: {
text: 'Distributions'
}
},
series: {{ chart.series|raw }}
};
$('#linechart').highcharts(options);
})
Maybe it's better if you use HTML5 data attributes: https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_data_attributes
In you view add some script tags and assign a javascript vraible to the twig variable. Don't forget to quote the twig (if required).
Firstly, I would ensure that the $url always had a value;
return $this->render('MyWebBundle:Player:show.html.twig', array(
'file' => $file,
'url' => (empty($url)) ? '' : $url,
'context' => $context,
'player' => $player,
'agentInWhiteList' => $agentInWhiteList
));
Something like;
<script>
var jsVar = '{{ url }}';
var html = false;
if (jsVar.length > 0) {
html = '<iframe src=\''+ jsVar +'\' name=\'viewerIframe\' id=\'viewerIframe\' width=\'100%\'allowfullscreen webkitallowfullscreen height=\'100%\' style=\'border:0px\'></iframe>';
}
// test html !== false before using it
</script>
Twig malforms my array keys and adds " " brackets to my array keys passed from a symfony2 controller.
The array is passed to a Javascript graphics library which requires:
[{x:"disabled test object",y:"17",label:"disabled test object"}]
Instead {{ array|json_encode|raw }} as suggested by the Twig docs and other SO questions I've read through returns the unreadable:
[{"x":"disabled test object","y":"17","label":"disabled test object"}]
I figure this should not be complicated to achieve but going through the json_encode options so far has not resulted in a clear answer. I am unsure whether there is something I can do from PHP so I've added the tag for now.
EDIT:
I am now attempting to step through the array manually using Twig. {{dump(points)}} confirms it is filled properly
{% set points = chart.dataPoints|json_encode|raw %} <=== this was the problem
dataPoints:
{% for point in points %}
{{ dump(point) }}
{ x: {{ point.x }}, y: {{ point.y }}, label: {{ point.label }} }
{% if loop.lastIndex != true %}
,
{% endif %}
{% endfor %}
But this does not work either as the dump is never reached. Is this the correct way of trying to access objects in a foreach via Twig though? This code is an amalgamation of several Twig docs tutorials.
EDIT 2, the solution:
The line {% set points = chart.dataPoints|json_encode|raw %} turned the whole array into a single string, making it impossible for javascript to interpret as an array. After removing this, all that was left was to make sure the query result had the proper array keys and to transform the X-axis data before passing it to Twig.
$i = 0;
$points = array();
/** #var array $query_result*/
foreach($query_result as &$row) {
foreach($row as $value) {
$point[] = [
'x' => ($i)*10,
'y' => $value['y'],
'label' => $value['label']
];
$points[$i] = $point;
$i++;
}
}
Quotes are not a problem for CanvasJS. As you can see in the example below, "x": works (I took this example):
window.onload = function () {
var chart = new CanvasJS.Chart("chartContainer",
{
title:{
text: "Top Oil Reserves"
},
data: [{
dataPoints: [
{ x: 1, y: 297571, label: "Venezuela"},
{ "x": 2, "y": 267017, label: "Saudi" }
]
}]
});
chart.render();
}
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/canvasjs/1.7.0/canvasjs.min.js"></script>
</head>
<body>
<div id="chartContainer" style="height: 200px; width: 100%;"></div>
</body>
</html>
So we need to provide a JSON array for dataPoints:
Define the PHP array in your Controller's function and pass it to the template:
public function myAction()
{
// …
$json = array(
array(
'x' => 1,
'y' => 297571,
'label' => 'Venezuela',
),
array(
'x' => 2,
'y' => 267017,
'label' => 'Saudi',
),
);
return array(
// …
'json' => $json,
);
}
Display the array in the template and pass it to dataPoints :
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/canvasjs/1.7.0/canvasjs.min.js"></script>
<script>
var json = {{ json|json_encode|raw }};
window.onload = function () {
var chart = new CanvasJS.Chart("chartContainer",
{
title:{
text: "Top Oil Reserves"
},
data: [{
dataPoints: json
}]
});
chart.render();
}
</script>
<div id="chartContainer" style="height: 300px; width: 100%;"></div>
The rendered output will be:
// …
<script>
var json = [{"x":1,"y":297571,"label":"Venezuela"},{"x":2,"y":267017,"label":"Saudi"}];
// …
CanvasJS will be able to read this JavaScript array and display the chart.
It looks like the first one is a JavaScript object, and the second one is JSON, try running JSON.parse on the string like this to convert it back in to an object:
var fixed = JSON.parse('[{"x":"disabled test object","y":"17","label":"disabled test object"}]');
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse