Select2 set selected not working on pagination option - javascript

I've using select2 pagination
here is my javascript code :
$("#propinsi").select2({
width: "100%",
placeholder: "Provinsi",
ajax: {
url: "{{ route('propinsi') }}",
dataType: "json",
data: function (params) {
return {
term: params.term || '',
page: params.page || 1,
page_limit: 10,
};
}
// cache: true
}
});
and then passing to the method on controller :
public function provinsi($page, $term, $page_limit, $kode_negara){
$offset = ($page - 1) * $page_limit;
$result = [];
$query = DB::table('m_wilayah_provinsi')->where(function($query) use ($kode_negara) {
$query->where('id_negara', $kode_negara);
})->select('id AS id', 'provinsi AS text');
// if (!empty($term)) {
// $query->where('provinsi', 'like', '%'.$term.'%');
// }
$count = $query->count();
$endCount = $offset + $page_limit;
$morePages = $count > $endCount;
$query = $query->skip($offset)->take($page_limit)->get();
$result = [
'results' => $query,
'pagination' => [
'more' => $morePages
]
];
return response()->json($result);
}
for displaying json data is working fine,but i cannot set selected.
I've try set setected like this but still not working :
$("#propinsi").val(1).trigger("change");
and
$("#propinsi").val(1);
Anyone can help me out ?

Try this:
$("#propinsi").select2('data', {id: 100, a_key: 'Lorem Ipsum'});

Related

Controller API return to Ajax a response with a status 200 but an empty array

I am totaly stuck with an Ajax request. I m trying to send a response to Ajax with an encoded array to json. Ajax get a status 200 response, but only strings are sent ; not my variables.
I wonder if the probleme is due to the asynchronous... When I test with Postman, i can see the full response but Js give to me : {"recipies":[]}.
Thanks for your help.
Ajax :
searchByIngredients: function () {
console.log('Search for recipies');
var array = [];
var ingredients = $('.span-ingredient');
ingredients.each(function () {
array.push(this.innerHTML);
});
console.log(array);
console.log(Array.isArray(array));
$.ajax(
{
url: Routing.generate('shopping_list_by_ingredients_ajax'),
type: "POST",
contentType: "application/json",
dataType: "json",
data: JSON.stringify(array)
}).done(function (response) {
if (null !== response) {
console.log('ok : ' + JSON.stringify(response));
console.log(typeof(response));
} else {
console.log('Error');
}
}).fail(function (jqXHR, textStatus, error) {
console.log(jqXHR);
console.log(textStatus);
console.log(error);
});
}
};
Controller :
/**
* #Route("/by-ingredient-ajax", name="shopping_list_by_ingredients_ajax", options={"expose"=true}, methods={"GET","POST"})
*
* #return JsonResponse|Response
*/
public function createShopplistByIngredientsAjax(Request $request, RecipeIngredientRepository $recipeIngredientRepository, RecipeRepository $recipeRepository)
{
if ($request->isMethod('POST')) {
$dataIngredients = json_decode($request->getContent());
$dataIngredients = $request->getContent();
// Sorry for this :/
$arrayIngredients = explode(', ', $dataIngredients);
$text = str_replace("'", '', $arrayIngredients);
$text2 = str_replace('[', '', $text);
$text3 = str_replace(']', '', $text2);
$recipiesArray = [];
// Get matching RecipeIngredient
foreach ($text3 as $data) {
/**
* #return RecipeIngredient()
*/
$recipeIngredients = $recipeIngredientRepository->findBy([
'name' => $data,
]);
foreach ($recipeIngredients as $recipeIng) {
$name = $recipeIng->getName();
$recipeNames = $recipeRepository->findRecipeByKeywwords($name);
foreach ($recipeNames as $recipeName) {
/**
* #return Recipe()
*/
$recipies = $recipeRepository->findBy([
'id' => $recipeIng->getRecipe(),
]);
// Built array with names & ids of recipies
foreach ($recipies as $key => $recipe) {
$recipeName = $recipe->getName();
$recipeId = $recipe->getId();
$recipiesArray[] = ['name' => $recipeName];
$recipiesArray[] = ['id' => $recipeId];
}
}
}
}
$response = new Response();
$response->setContent(json_encode([
'recipies' => $recipiesArray,
]));
$response->headers->set('Content-Type', 'application/json');
return $response;
}
return new Response(
'Something wrong...',
Response::HTTP_OK,
['content-type' => 'text/html']
);
Repository :
/**
* #return Recipe[] Returns an array of Recipe objects
*/
public function findRecipeByKeywwords($value)
{
return $this->createQueryBuilder('r')
->andWhere('r.name LIKE :val')
->setParameter('val', '%'.$value.'%')
->orderBy('r.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getArrayResult();
}
composer require jms/serializer-bundle
After you have installed the package, you just need to add the bundle to your AppKernel.php file:
// in AppKernel::registerBundles()
$bundles = array(
// ...
new JMS\SerializerBundle\JMSSerializerBundle(),
// ...
);
The configured serializer is available as jms_serializer service:
$serializer = $container->get('jms_serializer');
$json=$serializer->serialize(['recipies' => $recipiesArray], 'json');
return new JsonResponse($json,200);
Symfony 2.1
$response = new Response(json_encode(array('recipies' => $recipiesArray)));
$response->headers->set('Content-Type', 'application/json');
return $response;
Symfony 2.2 and higher
You have special JsonResponse class, which serialises array to JSON:
use Symfony\Component\HttpFoundation\JsonResponse;
//
//
return new JsonResponse(array('recipies' => $recipiesArray));
https://symfony.com/doc/current/components/http_foundation.html

Reduce choice list in select2 dropdown (when searching)

When I use select2, the list of choice doesn't reduce while searching, which is pretty annoying when I have more than 50 choices..
I use symfony4 framework, with a route providing my tags that are in a DB:
/**
* #Route("/miseenpage/keywords.json", name="keywords", defaults={"_format": "json"})
*/
Then I init my select2 with this code provided by the symfony Tags plugin:
$( document ).ready(function() {
initTags($('input[name$="[tagsText]"]'));
});
// TAGS
function initTags($input) {
if($input.length) {
$input.attr('type', 'hidden').select2({
width: '85%',
tags: true,
tokenSeparators: [","],
createSearchChoice: function (term, data) {
if ($(data).filter(function () {
return this.text.localeCompare(term) === 0;
}).length === 0) {
return {
id: term,
text: term
};
}
},
multiple: true,
ajax: {
url: $input.data('ajax'),
dataType: "json",
data: function (term, page) {
return {
q: term
};
},
results: function (data, page) {
return {
results: data
};
}
},
initSelection: function (element, callback) {
var data = [];
function splitVal(string, separator) {
var val, i, l;
if (string === null || string.length < 1) {
return [];
}
val = string.split(separator);
for (i = 0, l = val.length; i < l; i = i + 1) {
val[i] = $.trim(val[i]);
}
return val;
}
$(splitVal(element.val(), ",")).each(function () {
data.push({
id: this,
text: this
});
});
callback(data);
}
});
}
}
Here is the result in my webpage before searching:
Here is after searching:
As you can see, the list is still the same, just the result is underlined. I'd like to filter the result depending on what I search, so I don't have to scroll all the way until I find my underlined term.
As it is the basic working of Select2, I guess there is an configuration problem in my JS.
I instanciated this value on load:
let currentSearch = false;
Then I changed the "AJAX" section of my JS so it loops around the list with the searched value:
ajax: {
url: $input.data('ajax'),
dataType: "json",
data: function (term) {
currentSearch = term;
return {
q: term
};
},
results: function (data) {
let returnTab = [];
data.forEach(function(e) {
if(e.text.includes(currentSearch)){
returnTab.push(e);
}
});
return {
results: returnTab
};
}
},
I'm pretty sure there is a cleaner/simpler way of doing this, but for moment it's a quickfix.
Just a basic example with some code to show how we use Select2 (v4.0.3, 3.5 may be quite different) with Ajax
On a twig, we have for example :
$("#users").css('width', '100%').select2({
minimumInputLength: 3,
ajax: {
url: "{{ path('api_search_user') }}",
dataType: 'json',
delay: 500,
data: function (params) {
return {
needle: params.term // Here we send user input to the controller
};
},
processResults: function (data) {
return {
results: data
};
},
cache: false
}
});
And we have a controller with a function to search for users :
/**
* #Route("/search_users", name="api_search_users")
* #param Request $request
* #return JsonResponse
*/
public function searchUsersAction(Request $request)
{
$needle = $request->get('needle'); // Here we retrieve user input
$users = $this->get(User::class)->searchUsers($needle);
return new JsonResponse($users );
}
EDIT following you last comment
This value is not valid
That's because your value isn't part of the select when the formbuilder add the field. You must add an addEventListener on PRE_SUBMIT to dinamically add this value. You can do it this way :
// Define form modifier
$usersFormModifier = function (FormInterface $form, $users) use ($options) {
$choices = array();
if(is_array($users)) {
$choices = $users;
}
$form->add(
'users',
EntityType::class,
array(
'label' => 'conversation.form.users',
'multiple' => true,
'class' => 'AppBundle\Entity\Security\User',
'choices' => $choices,
'choice_label' => function (User $user) {
return $user->getLastName() . " " . $user->getFirstName();
},
'attr' => array(
'placeholder' => 'default.search_person'
)
)
);
};
// On PRE_SET_DATA, we load users from our object (which only contains their IDs)
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($usersFormModifier) {
$usersFormModifier($event->getForm(), $event->getData()->getUsers()->toArray());
}
);
// On PRE_SUBMIT, we add the options, so the select will accept newly added values
$builder->addEventListener(
FormEvents::PRE_SUBMIT,
function (FormEvent $event) use ($usersFormModifier) {
$data = $event->getData();
$users = null;
if(isset($data['users'])) {
$users = $this->entityManager->getRepository('AppBundle:Security\User')->findBy(array('id' => $data['users']));
}
$usersFormModifier($event->getForm(), $users);
}
);
As I said at the beginning, if you don't have so muchs tags, and they don't evolve regularly, you can construct your select with all your tags and avoid all the Ajax part of the Select2 javascript code ! (I think it will be easier and sufficient for your case)

DataTable column is showing object and not displaying actually value?

I am trying to populate DataTable with my Data but DataTable is showing object in columns and not printing the actual values!
Function in Controller:
public function getEvaluationSymptomsAction() {
//Get Evaluation Symptoms from DataBase
$evaluation_symptoms = CxEbEvaluationSymptom::getAllEvaluationSymptomsWithNameForDataTable();
$inferredRemedies = array();
$additonalRemedies = array();
$data = array();
foreach ($evaluation_symptoms as $key => $symptom) {
$data[ $key ][ 'id' ] = $symptom[ 'id' ];
$data[ $key ][ 'title' ] = $symptom[ 'title' ];
// Get Inferred Remedies By Symptom ID
$inferredRemedies = CxEbEvaluationSymptom::getInferredRemediesBySymptomId($symptom[ 'id' ]);
$additonalRemedies = CxEbEvaluationSymptom::getAdditionalSymptomRemediesBySymptomId($symptom[ 'id' ]);
$data[ $key ][ 'remedy' ] = $inferredRemedies;
$data[ $key ][ 'additional-remedy' ] = $additonalRemedies;
$data[ $key ][ 'date_created' ] = $symptom[ 'date_created' ];
}
//print_r($data);exit;
// Return data array
return array('data' => $data);
// Return data
}
The above function return the below array: (NOTE the below array is var_dump version actually data is in JSON format)
Array code is here
Queries:
public static function getInferredRemediesBySymptomId($symptomId){
$queryBuilder = new Builder();
return $queryBuilder
->from(array('es' => 'Cx\EbFront\Models\Evaluation\CxEbEvaluationSymptom'))
->leftJoin('Cx\EbFront\Models\Evaluation\CxEbEvaluationSymptomCause', 'es.id = esc.evaluation_symptom_id','esc')
->leftJoin('Cx\EbFront\Models\Evaluation\CxEbEvaluationCause','esc.evaluation_cause_id = ec.id','ec')
->leftJoin('Cx\EbFront\Models\Evaluation\CxEbEvaluationCauseRemedy','ec.id = ecr.evaluation_cause_id','ecr')
->leftJoin('Cx\EbFront\Models\Evaluation\CxEbEvaluationRemedy','ecr.evaluation_remedy_id = er.id', 'er')
//->leftJoin('Cx\EbFront\Models\Evaluation\CxEbEvaluationSymptom', 'es.id = :ID:', 'es')
->columns('er.id, er.title')
->where('es.is_active = 1')
->andWhere('es.id = :ID:')
->getQuery()
->execute(array('ID' => $symptomId))
//->execute()->setHydrateMode(Resultset::HYDRATE_ARRAYS)
->toArray();
}
/**
* A
* Data for column Additonal Remedies in DataTable
* #return array
*/
public static function getAdditionalSymptomRemediesBySymptomId($symptomId){
$queryBuilder = new Builder();
return $queryBuilder
->from(array('er' => 'Cx\EbFront\Models\Evaluation\CxEbEvaluationRemedy'))
->innerJoin('Cx\EbFront\Models\Evaluation\CxEbEvaluationSymptomRemedy', 'er.id = esr.evaluation_remedy_id','esr')
->columns('er.id, er.title')
->where('er.is_active = 1')
->andWhere('esr.evaluation_symptom_id = :ID:')
->getQuery()
->execute(array('ID' => $symptomId))
->toArray();
}
The below is the JS code for initializing the DataTable:
function EbEvaluationSymptom(){
var $body = $('body');
var $CxRecordsTable = $('#cx-records-table');
// Init the DatTable using the Cx Admin DataTable plugin
cx.common.data.cxAdminDataTables.EbEvaluationSymptom = $CxRecordsTable.cxAdminDataTable({
ajaxUrl: '<?php echo $this->CxHelper->Route('eb-admin-get-evaluation-symptoms')?>',
columns: [
cx.common.admin.tableEditColumn('id'),
{ data: 'title' },
{ data: 'remedy' },
{ data: 'additional-remedy' },
{ data: 'date_created' }
],
});
};
JSON Response:
https://pastebin.com/g2mhhS4D
DataTables doesn't know how to format the array of object(s) supplied for remedy & additional-remedy.
Assuming there is always one object in each of those arrays, you want to access the first object in each array and use its title property:
columns: [
cx.common.admin.tableEditColumn('id'),
{ data: 'title' },
{ data: 'remedy.0.title' },
{ data: 'additional-remedy.0.title' },
{ data: 'date_created' }
],
If you plan to have more than 1 element in each array, you'll need a different approach

Sending array attribute of object to Ajax

(sorry for my english)
I have a little problem.
Shop Bascket
I want to store at session a shop-bascket, so I created the php/classes/bascket.php:
class Product
{
private $id;
private $quantity;
function __construct(int $id, int $q)
{
$this->id = $id;
$this->quantity = $q;
}
...
}
class Bascket
{
private $products = array();
/* for testing */
function __construct()
{
$this->products[] = new Product(26, 1006);
}
function add(int $id, int $quantity)
{
...
}
function delete(int $id, int $quantity)
{
...
}
function __get($field) {
return $this->$field;
}
}
Using the Shop Bascket
And I use this class on session anywhere I want:
include "php/classes/bascket.php"; (*or another correct path*)
session_start();
if(!isset($_SESSION["bascket"])) {
$_SESSION["bascket"] = serialize(new Bascket());
}
$bascket = unserialize($_SESSION["bascket"]);
Trying to display Bascket Shop with Ajax
Because I want to show the bascket on pressing a button, I made an ajax which do the following thing:
function display_bascket() {
$.ajax({
url: 'php/take_bascket.php',
dataType: 'text',
cache: false,
contentType: false,
processData: false,
type: 'post',
success: function(bascket){
//bascket = JSON.parse(bascket);
//bascket = jQuery.parseJSON(bascket);
$("#content").html(bascket);
}
});
}
And I tried a lot to can display the correct thing in take_bascket.php to receive a good array, or a json in ajax.
take_bascket.php
<?php
session_start();
include "classes/bascket.php";
if(!isset($_SESSION["bascket"])) {
$_SESSION["bascket"] = serialize(new Bascket());
}
// I tried many variants:
var_dump($_SESSION["bascket"]);
/*
* output:
* string(116) "O:3:"Bascket":1:{s:12:"Bascketproducts";a:1:{i:0;O:6:"Product":2:{s:10:"Productid";i:26;s:17:"Productquantity";i:1006;}}}"
*
* and I don't know how to handled it in ajax to get the products array
*/
var_dump(unserialize($_SESSION["bascket"]));
/*
* output:
* object(Bascket)#1 (1) { ["products":"Bascket":private]=> array(1) { [0]=> object(Product)#2 (2) { ["id":"Product":private]=> int(26) ["quantity":"Product":private]=> int(1006) } } }
*
* and I don't know how to handled it in ajax to get the products array
*/
var_dump(json_encode($_SESSION["bascket"]));
/*
* output:
* string(158) ""O:3:\"Cos\":1:{s:12:\"\u0000Cos\u0000products\";a:1:{i:0;O:6:\"Product\":2:{s:10:\"\u0000Product\u0000id\";i:26;s:17:\"\u0000Product\u0000quantity\";i:1006;}}}""
*
* and I don't know how to handled it in ajax to get the products array
*/
var_dump(((unserialize($_SESSION["bascket"]))->products));
/*
* output:
* array(1) { [0]=> object(Product)#2 (2) { ["id":"Product":private]=> int(26) ["quantity":"Product":private]=> int(1006) } }
*
* and I don't know how to handled it in ajax to get the products array
*/
var_dump(((unserialize($_SESSION["bascket"]))->products[0]));
/*
* output:
* object(Product)#2 (2) { ["id":"Product":private]=> int(26) ["quantity":"Product":private]=> int(1006) }
*
* and I don't know how to handled it in ajax to get the products array
*/
Conclusion
As you can see I also tried different ways of manipulate the output in ajax. But or it is a string and I can't convert it in array. Or I can't make it json, etc.
Please
Please, can you try find a complete solution? I mean for take_bascket.php, but also for what I have to do in display_bascket() in js.
thank you in advance
Edit:
I did as someone said in a post:
php/classes/bascket.php
<?php
class Product
{
private $id;
private $quantity;
function __construct(int $id, int $q)
{
$this->id = $id;
$this->quantity = $q;
}
function decrease(int $value)
{
...
}
function increase(int $value) {
...
}
public function toArray(){
return [
'id' => $this->id,
'quantity' => $this->quantity,
];
}
}
class Bascket
{
private $products = array();
/* for testing */
function __construct()
{
$this->products[] = new Product(26, 1006);
}
function add(int $id, int $quantity)
{
...
}
function delete(int $id, int $quantity)
{
...
}
public function toJson(){
$products = [];
foreach ($this->products as $product) {
$products[] = $product->toArray();
}
return json_encode(
[
'products' => $products
],
JSON_PRETTY_PRINT
);
}
function __get($field) {
return $this->$field;
}
}
And that's how I would theoretical create a PHP JSON easier.
But look at take_bascket.php:
<?php
session_start();
include "classes/bascket.php";
if(!isset($_SESSION["bascket"])) {
$_SESSION["bascket"] = serialize(new Bascket());
}
var_dump(((unserialize($_SESSION["bascket"]))->toJson()));
/*
* output:
* string(98) "{ "products": [ { "id": 26, "quantity": 1006 } ] }"
*/
Trying to use it in display_bascket():
function display_bascket() {
$.ajax({
url: 'php/take_bascket.php',
dataType: 'text',
cache: false,
contentType: false,
processData: false,
type: 'post',
success: function(bascket){
//bascket = JSON.parse(bascket);
$("#content").html(bascket);
}
});
}
If I don't use JSON.parse(), it'll display the next plain text:
string(98) "{ "products": [ { "id": 26, "quantity": 1006 } ] }"
Instead, if I use JSON.parse(), I have a console error:
Uncaught SyntaxError: Unexpected token s in JSON at position 0
at JSON.parse (<anonymous>)at Object.success (display_bascket.js:10)
at j (jquery.js:2) at Object.fireWith [as resolveWith] (jquery.js:2)
at x (jquery.js:4) at XMLHttpRequest.b (jquery.js:4)
What should I do?
I suggest that in each object you create a method that will return a JSON representation of that object.
For instance (filename: products.php):
class Product {
private $name;
private $value;
private $quantity;
public function __construct($name, $value, $quantity){
$this->name = $name;
$this->value = $value;
$this->quantity = $quantity;
}
public function toArray(){
return [
'name' => $this->name,
'value' => $this->value,
'quantity' => $this->quantity,
];
}
}
class Basket{
private $products = [];
public function addProduct(Product $p){
$this->products[] = $p;
}
public function toJson(){
$products = [];
foreach ($this->products as $p) {
$products[] = $p->toArray();
}
return json_encode(
[
'products' => $products
],
JSON_PRETTY_PRINT
);
}
}
$b = new Basket();
$b->addProduct(new Product('Apple', 1, 5));
$b->addProduct(new Product('Banana', .5, 2));
$b->addProduct(new Product('Carrots', .35, 6));
echo $b->toJson();
This will generate a JSON object that you can use with jQuery .getJSON() method.
Like the example below (filename: products.html):
<html>
<head>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"> </script>
</head>
<body>
<h3>Product list</h3>
</body>
<script>
$(function(){
$.getJSON( "products.php", function( data ) {
console.log(data);
var items = [];
$.each( data.products, function( key, val ) {
items.push( "<li>Name: " + val.name + " | Quantity: " + val.quantity + " | Price: " + val.value + "</li>" );
});
$( "<ul/>", {
html: items.join( "" )
}).appendTo( "body" );
});
});
</script>
</html>

Associative array not an array when passed to controller thru AJAX

I'm trying to pass this array var data_array into my controller thru AJAX
This is the value of var data_array when I use alert(JSON.stringify(data_array));
This is my AJAX method
var project_details = $.extend({}, data_array);
$.ajax({
type: "POST",
url: "<?php echo base_url('PPMP_controller/submitPPMP'); ?>",
data: { data_array : $.param(project_details) },
dataType: 'json',
success: function(data) {
alert('PPMP submission success!');
alert(data);
},
error: function(errorw) {
console.log(errorw);
}
});
This is my PPMP_controller
public function submitPPMP(){
$data_array = $this->input->post('data_array');
$value = $this->PPMP_model->submitPPMP($data_array);
echo json_encode($value);
}
This is my model
function submitPPMP($data_array){
$date_format = 'DATE_W3C';
$date_submitted = standard_date($date_format);
$data = array(
'user_id' => 1,
'date_submitted' => $date_submitted,
'first_lvl_status' => 0,
'second_lvl_status' => 0,
'third_lvl_status' => 0,
'fourth_lvl_status' => 0,
'submitted' => 1
);
$this->db->insert('project', $data);
$id = $this->db->insert_id();
if(is_array($data_array) || is_object($data_array)){
return "yes";
foreach($data_array as $object){
$project_details = array(
'project_id' => $id,
'supply_id' => $object->supply_id,
'supply_description' => $object->supply_description,
'quantity' => $object->quantity,
'price' => $object->price,
'jan' => $object->jan,
'feb' => $object->feb,
'mar' => $object->mar,
'apr' => $object->apr,
'may' => $object->may,
'jun' => $object->jun,
'jul' => $object->jul,
'aug' => $object->aug,
'sep' => $object->sep,
'oct' => $object->oct,
'nov' => $object->nov,
'dec' => $object->dec
);
$this->db->insert('project_details', $project_details);
}
}
else{
return "no";
}
return $this->db->last_query();
}
However the array passed from controller to model is not an array since it doesn't go thru the line if(is_array($data_array) || is_object($data_array)) instead it goes to the else condition and return "no".
What might be causing this array not being passed an array from controller to model. Thank you for the help. I am using Codeigniter 3.0 as an MVC framework.
you are passing json to your model not array , when it comes to your model it should be ,
try var_dump($data_array) to check its data type i.e json or object or array
$data_array = json_decode($data_array); // to get object
$data_array = json_decode($data_array,true); // to get array
Your PPMP_controller should be
public function submitPPMP(){
$data_array = $this->input->post('data_array');
$data_array = json_decode($data_array);
$value = $this->PPMP_model->submitPPMP($data_array);
echo json_encode($value);
}

Categories