I'm using Charts,js by devex (find the link to the documentation by clicking here). I'm also using the Laravel framework. I need to generate some JQuery on the server side to output the graphs I want. I am passing $json_micromarket_participants which is an array of objects (rows from database query) that are json_encoded in my controller. Each object has a Home_name and Average_Occupancy property.
For some reason my foreach loop doesn't work, i.e. I get the following error:
Invalid argument supplied for foreach()
My question is twofold:
1. Why doesn't it work?
2. Would this code work anyway to generate name
and value pairs in jquery?
Code:
#section('content')
<script type="text/javascript">
var chartDataSource = {{ $json_micromarket_participants }};
$(function () {
$("#chartContainer").dxChart({dataSource: chartDataSource,
commonSeriesSettings:{argumentField: 'Home_name'},
series: [
#foreach($json_micromarket_participants as $micromarket_participant)
{
name: '{{$micromarket_participant->Home_name}}',
valueField: '{{$micromarket_participant->Average_Occupancy}}'
},
#endforeach
]
});
})
</script>
<div id="chartContainer" style="max-width:700px; height:300px;"></div>
#stop
In the controller, here's how $json_micromarket_participants is set. It's all fine on that side I think...
$micromarket_participants = DB::table('homes')
-> select(array('*', DB::raw('SQRT(POW('.$Eastings.' - `Eastings`,2) + POW('.$Northings.' - `Northings`,2)) AS distance')))
-> having('distance', '<', $micromarket_size)
-> get();
$json_micromarket_participants = json_encode($micromarket_participants);
It is not working because you have encoded $micromarket_participants into json, making it a string, not an array.
I think $micromarket_participants is the array of objects in this case, so you should just use this in your view:
#foreach($micromarket_participants as $micromarket_participant)
I think your issue is that you are calling json_encode on the $micromarket_participants object, which I don't think that will return what you want. Instead, try just calling the toJson method on the returned collection:
$json_micromarket_participants = $micromarket_participants->toJson();
Related
I'm trying to return a query made in a controller to the view file so I can use that data in my form. But I am unable to successfully return the data without errors. I know the function is working because it returns the right data but has an error.
Here is my CustomersController fill function which is running the sql query.
public function fill(){
$layout = 'ajax';
$this->autoRender = false;
if ($this->request->is('post')) {
$id = $this->request->data['id'];
$query = $this->Customers->find()
->where([
'id' => $id
])->first();
echo json_encode($query);
}
}
and here is my blah.ctp which is the view file.
<?php use Cake\Routing\Router; ?>
<?= $this->Form->create(Null, ['type' => 'POST']) ?>
<?php
echo $this->Form->input('customer_id', ['options' => $customers, 'empty' => true,'id'=>'customers']);
?>
<?= $this->Form->end() ?>
<script>
document.getElementById('customers').addEventListener('change',function(){
var id = this.value;
var csrfToken = $('[name=_csrfToken]').val();
$.ajax({
type: "POST",
url: '<?php echo Router::url(array("controller" => "Customers", "action" => "fill")); ?>',
data: {'id' : id},
beforeSend: function(xhr){
xhr.setRequestHeader('X-CSRF-Token', csrfToken);
},
success: function(data){
alert(data);
}
});
});
</script>
Currently this is what happens when I select a customer in my drop down box which triggers the script in the view.
As you can see it returns the array of data I need but also has the error cannot emit headers. I have tried solving this error following other questions on stack overflow but can't solve it.
I've tried using $this->set instead of echo json_encode but it always returns nothing. I'm not sure what other way to do this.
First of all, If you're selecting a single record by a unique ID, you can call
->get($id) on the table object directly, instead of building a query chain with ->find().
CakePHP 3.x should automatically handle converting your view to JSON by using the RequestHandlerComponent. Typically, you must enable it if your scaffolding or installation didn't.
1) Enable request handler component. (If not already enabled) https://book.cakephp.org/3.0/en/controllers/components/request-handling.html
2) Remove the echo json_encode($query) line; you should not echo anything as this will break the request/response cycle. This is the cause of your error.
Instead, you should serialize your data to the view. Assuming you have the fetched data in $data: $this->set(compact('data')). Then, make sure you add $this->set('_serialize', ['data']) (again, assuming the data is stored in variable name 'data').
3) Reference this doc for information on how you can request the json. You can use a file extension (.json, .xml).
Also, make sure you add the 'Accept: application/json' header to your request.(https://book.cakephp.org/3.0/en/development/routing.html#Cake\Routing\Router::extensions).
I apologize for the fuzzy response. There are many ways to achieve this with CakePHP3. Please see this doc page for more information: https://book.cakephp.org/3.0/en/views/json-and-xml-views.html
I'm using select2 jquery plugin, and laravel form model binding to render the data from the server.
While everything else works fine, it doesn't rendered the tags that has been attached to the post as selected option.
there must be something which I'm unaware of, here's my view part.
<div class="form-group">
{!! Form::label('tag_list','Tags:') !!}
{!! Form::select('tag_list[]', $tags,null,['id'=>'tag_list', 'class'=>'form-control','multiple']) !!}
</div>
// This is the select 2 script
$('#tag_list').select2({
'placeholder':'Choose Tags',
tags:true,
tokenSeparators:[",", " "],
createTag:function(newTag){
return{
id:'new:' + newTag.term,
text:newTag.term + '(new)'
};
}
});
And this is a getTagListAtrribute function in Article model
// This is the getTagListAttribute function
public function getTagListAttribute(){
return $this->tags->lists('post_id')->all();
}
And I load the edit form from the controller like this:
public function article_edit($slug){
// fetch the articles.
//$article = DB::table('articles')->where('slug',$slug)->first();
$article = Article::where('slug',$slug)->first();
/*echo '<pre>';
print_r($article->title);
die();*/
$tags = DB::table('tags')->lists('name','tag_id');
$categories=DB::table('categories')->lists('category_name','category_id');
return view('admin.pages.edit', compact('article','tags','categories'));
}
I just want the tags which are associated with article be selected while the page loads, and which I've been unable of. So I'm in the need of help.
Well, since you have tagged the question as laravel-5.1. There are some changes been made to the lists method.
In Laravel 5.0.* it returned just the plain array of keys and/or values that you pass in the lists method. More info here
In Laravel 5.1.*, it returns a Collection object. More Info - Just the code documentation
So, the solution that you are looking for is:
In controller, do this:
$tags = DB::table('tags')->lists('name','tag_id')->toArray();
Or in the view file, do this:
{!! Form::select('tag_list[]', $tags->toArray(), null,['id'=>'tag_list', 'class'=>'form-control','multiple']) !!}
And that should do the trick for you.
EDIT 1:
Remove all() method from getTagsListAttribute(). That is not at all required.
Why are you using DB Facade for querying the tags table ? Since you have already established the relationship, you are unnecessarily executing the SQL Statements. Avoid that as much as you can.
You should get it by simply doing this:
$tags = $article->tags;
EDIT 2:
Are you sure that you have tag_id column in tags table ? I doubt that. I guess that must be a typo.. By mistakenly, you must have typed tag_id instead of id. Cross verify it for the confirmation.
Hope this helps you out. Happy Coding. Cheers.
Set select form tag like this
{!! Form::select('tag_list', $tags, $selected, ['id'=>'tag_list', 'name'=>'tag_list[]','class'=>'form-control','multiple']) !!}
Pass the ids to be selected as array in third ($selected).
So, if
$tags = ['1'=>'one', '2'=>'Two', '3'=>'Three']
and you want One and Three selected, pass these ids as an array to the form select as the third parameter.
so, $selected = [1,3];
I am using knockjs and I have created dynamic observableArrays in js file.
Ex. product+productid which creates a dynamic observableArrays as product123.
I want to use this in a data bind foreach loop and want to create this variable dynamically again in html file.
Something like : data-bind="foreach: { data: "product"+product.id()()}
So this "product"+product.id()() binding should call my product123() array.
How can I achieve this?
Hey it worked with vm['product'+product.id()]
You can use $data to refer to the current context, and use array notation to index your dynamically-named element.
vm = {
product: ko.observable('123'),
product123: ko.observableArray([
'one', 'two', 'three'
])
};
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div data-bind="foreach: $data['product'+product()]">
<div data-bind="text: $data"></div>
</div>
struggling to figure out how to best do what I would normally in simple PHP.
I have the following URL:
/viewbuild/2
The aim is that viewbuild is the view and 2 is the id of the database row.
Normally It would simply be:
$id = $_GET['id'];
But cant figure out to do it PROPERLY using laravel.
This is my route:
Route::get('viewbuild', function()
{
return View::make('viewbuild');
});
And on my view I have done e.g.:
<?php
$build = Build::find(20);
?>
{{ $build->id }}
This correctly searches the builds table for a row with the id of 2 and then displays its id.
What I now want to do is pull the '20' value from the URL.
I have tried:
Route::get('/viewbuild/{build_id}', function($build_id = null)
{
$data = array(
'build_id' => $build_id,
);
return View::make('viewbuild', $data);
});
And then on my view:
$build = Build::find(build_id);
But I get undefined constant errors.
Any help on this?
Basically i can see two things from quick looking at your code:
A typo when setting the array to be passed to the view build_ud should be build_id i presume
You are referencing a constant for the build_id (no $ sign) in your view instead of the passed variable which is passed to the view. Ie:
$build = Build::find(build_id);
should be:
$build = Build::find($build_id);
Your route closure should look like this:
Route::get('/viewbuild/{build_id?}', function($build_id = null)
{
// Query the database here instead of inside the view
$build = Build::find($build_id);
return View::make('viewbuild', compact('build'));
});
Here is what I have so far:
var Item = Backbone.Model.extend({
defaults: {
id: 0,
pid: 0,
t: null,
c: null
},
idAttribute: 'RootNode_', // what should this be ???
url: 'page.php'
});
var ItemList = Backbone.Collection.extend({
model: Item,
url: 'page.php',
parse: function(data) {
alert(JSON.stringify(data)); // returns a list of json objects, but does nothing with them ???
}
});
var ItemView = Backbone.View.extend({
initialize: function() {
this.list = new ItemList();
this.list.bind('all', this.render, this);
this.list.fetch();
},
render: function() {
// access this.list ???
}
});
var view = new ItemView();
Current (expected) json response:
{
"RootElem_0":{"Id":1,"Pid":1,"T":"Test","C":"Blue"},
"RootElem_1":{"Id":2,"Pid":1,"T":"Test","C":"Red"},
"RootElem_2":{"Id":3,"Pid":1,"T":"Test2","C":"Money"}
}
This successfully polls page.php and the backend acts on $_SERVER['REQUEST_METHOD'] and returns the required information, however I don't know why the collection is not filled.
In the parse function of ItemList it properly shows me all the output, but it does nothing with it.
I left some comments in the code for some more precise questions, but the main question is why doesn't the collection populate with the obviously received data?
Modify your parse method to:
parse: function(response){
var parsed = [];
for(var key in response){
parsed.push(response[key]);
}
return parsed;
}
To follow conventions, change list inside ItemView to model. Also in render():
render: function() {
var template = _.template("<div>some template</div>");
this.model.each(function(item){
this.$el.append(template(item.toJSON()));
}, this);
return this;
}
The parse method you're supposed to be returning the data after doing whatever necessary parsing is required for it.
The common use case for parse would be if you're sending back an object of a form like:
{ "id" : "NaN", "tasks": [ *all your models in a list here *] }
then you'd use parse like so:
parse: function (data) {
return data.tasks
}
Backbone then handles the rest.
Is there a particular reason why you're sending the data back in that dictionary format? It's not exactly clear how you intend to map that to each model of the collection. Is the key irrelevant? if so, you should be passing back a list of the objects in the values.(Although see note at bottom). If not, and you want to attach it to the models, it should be moved to the object you're using as a value and send back a list.
* Note: Don't actually send back a JSON list bare. There is an exploit for GET requests that relies on lists being valid javascript on their own, where a malicious site can use the Array object and override it to use a script tag to your API to use the users credentials to pull down whatever information is available in that call. Instead, when wanting to send back a list you should use something like this:
{ result: [*list here*] }
Then you just use the parse method above to extract the list.