I'm working on a webapplication in Symfony2. At the moment I have several pages that include a search form where you can search for specific entities that belong to that page.
For example; I have a client page with an overview of client information. Here you can search for clients with a name like your search value. Thats no rocket science I guess.
At the front page I want to somehow search all my entities at once. I was thinking about combining the searches I already have, or maybe there is a function in Symfony that allows this?
Here's some of my code for the search(es) I have so far:
Live search action for clients:
public function liveSearchAction(Request $request)
{
$string = $this->getRequest()->request->get('sQuery');
$clients = $this->getDoctrine()
->getRepository('clientsBundle:client')
->findByLetters($string);
$response = new JsonResponse(array('clients' => $clients));
$response->headers->set('Content-Type', 'application/json');
return $response;
}
The repository function findByLetters:
public function findByLetters($string){
$query = $this->getEntityManager()
->createQuery(
'SELECT c FROM clientsBundle:client c
WHERE c.name LIKE :string'
)->setParameter('string', '%'.$string.'%');
$result = $query->getArrayResult();
return $result;
}
The AJAX call for returning searchresults
(function($, Handlebars, window, document, undefined) {
var that = this;
var oXHR;
var source = $("#searchResult").html();
var template = Handlebars.compile(source);
var action = $('#quickSearch').data('action');
var route = $('#quickSearch').data('route');
Handlebars.registerHelper('url', function(options) {
console.log(this, options);
return new Handlebars.SafeString(
Routing.generate(route, {'id': this.id})
);
});
$('#quickSearch').on('input',function() {
var $this = $(this);
var searchText = $this.val();
console.log('searching for: ' + searchText);
if (typeof oXHR !== 'undefined') {
oXHR.abort();
}
oXHR = $.ajax({
type: "POST",
url: action,
dataType: "json",
data: {
sQuery : searchText
},
success: function(response)
{
var html = template(response);
// console.log(html);
$('#list .list-group').html(html);
},
error: function(failresponse)
{
console.log( failresponse );
}
});
});
}).call(window.Test = window.Test || {}, jQuery, Handlebars, window, document);
As you might have noticed, the return of the AJAX call gets handled by handlebars.
Related
I'm trying to load a php file into a div on submission of a form. At the moment everything fires bar this line $('#signupform').load('newsletter-signup-call.php');, I've just got a simple echo request in there and it doesn't fire. If I goto that template it works though.
Where am I going wrong? Could I possibly fire two Ajax calls (as that in itself works) but there seems to be issues with load.
<script>
$("#signupForm").submit(function(e) {
e.preventDefault();
var form = $(this);
var email = $("#EmailAddress").val();
$.ajax({
type: "POST",
url: form.attr('action') + '?email=' + email,
data: form.serialize(),
beforeSend: function(){
$(".newsletter-loading").show().css({"display":"inline-block"});
},
success: function(data)
{
console.log(data); //data contain response from your php script
register_signup();
register_prefs();
(function() {
window.sib = {
equeue: [],
client_key: "xxx"
};
/* OPTIONAL: email for identify request*/
window.sib.email_id = email;
window.sendinblue = {};
for (var j = ['track', 'identify', 'trackLink', 'page'], i = 0; i < j.length; i++) {
(function(k) {
window.sendinblue[k] = function() {
var arg = Array.prototype.slice.call(arguments);
(window.sib[k] || function() {
var t = {};
t[k] = arg;
window.sib.equeue.push(t);
})(arg[0], arg[1], arg[2]);
};
})(j[i]);
}
var n = document.createElement("script"),
i = document.getElementsByTagName("script")[0];
n.type = "text/javascript", n.id = "sendinblue-js", n.async = !0, n.src = "https://sibautomation.com/sa.js?key=" + window.sib.client_key, i.parentNode.insertBefore(n, i), window.sendinblue.page();
})();
sendinblue.track('marketing');
$(".newsletter-loading").hide();
form.replaceWith("<br /><p>Thanks for signing up! You'll receive an email with your discount.</p>");
}
});
});
function register_prefs(){
var email = $("#EmailAddress").val();
Cookies.set('Address', email, { expires: 100000 });
$('#signupform').load('newsletter-signup-call.php');
}
function register_signup(){
ga( 'send', 'event', 'Newsletter Sign Up', 'submit' );
}
</script>
Try to console.log the response status to see what's going wrong
function register_prefs(){
//see if this function is triggered
console.log('register_prefs function triggered')
var email = $("#EmailAddress").val();
Cookies.set('Address', email, { expires: 100000 });
$('#signupform').load('newsletter-signup-call.php', function( response, status, xhr ){
console.log('Server response : ', response)//The serve response
console.log('Status Message : ', [xhr.status, xhr.statusText])//See the status of your request, if any error it should be displayed here
});
}
BUT, Why perform another server call with load, when your are already using ajax, you can return the html in the first call in a json object {Mydata: ..., MyHTML: ...} and just use $('#signupform').html(data.MyHTML) on success.
Also, not sure but I'm suspecting a malformed URL, try this instead '/newsletter-signup-call.php' or an absolute path just to be sure.
I have this working example where i have use $scope and $http in controller to fetch an col from database using get method in variable as given below
<script>
var fetch = angular.module('myapp', []);
fetch.controller('userCtrl', ['$scope', '$http', function ($scope, $http) {
$http({
method: 'get',
url: 'quizdb.php'
}).then(function successCallback(response) {
// Store response data
$scope.users = response.data;
});
}]);
</script>
now i want this same thing in my factory service i have where i am using hardcoded array. i want to replace the hardcoded array with dynamic array.
with php i am getting an array of but the problem is that i dont know how to implement this thing in factory in angular
my factory is as follows
(function(){
angular
.module("htcssquiz")
.factory("DataService",DataService);
function DataService(){
var dataObj = {
turtleData: turtleData,
quizQuestions: quizQuestions,
correctAnswer : correctAnswer
};
return dataObj;
}
var correctAnswer = [1,2,3,0,2,0,3,2,0,3];
var quizQuestions = [
{
type: "text",
text: "How much can a loggerhead weigh?",
possibilities: [
{
answer: "Up to 20kg"
},
{
answer: "Up to 115kg"
},
{
answer: "Up to 220kg"
},
{
answer: "Up to 500kg"
}
],
selected: null,
correct: null
}
so i want to replace this correctAnswer array with dynamic one.
please help me i am new to angular . thank you in advance.
I am using this factory DataService in The List controller using $inject as follows
(function(){
angular
.module("htcssquiz")
.controller("listctrl", ListController);
ListController.$inject = ['quizMetric','DataService'];
function ListController(quizMetric,DataService){
var vm = this;
vm.quizMetric =quizMetric;
vm.data = DataService.turtleData;
vm.activeTurtle = {};
vm.changeActiveTurtle = changeActiveTurtle;
vm.activateQuiz =activateQuiz;
vm.search = "";
function changeActiveTurtle(index){
vm.activeTurtle = index;
}
function activateQuiz(){
quizMetric.changeState("quiz", true);
}
}
}) ();
This will require a change to both your controller AND your service. The controller will now use the service as if it were the $http call:
fetch.controller('userCtrl', ['$scope', 'DataService', function ($scope, DataService) {
DataService.getCorrectAnswer().then(function (response) {
// Store response data
$scope.correctAnswer = response.data;
});
}]);
Your service will now take responsibility for making the $http call:
DataService.$inject = ['$http'];
function DataService($http){
var dataObj = {
...
getCorrectAnswer : function() {
return $http({
method: 'get',
url: 'quizdb.php'
});
}
};
return dataObj;
}
Admittedly, there are similar questions lying around on Stack Overflow, but it seems none quite meet my requirements.
Here is what I'm looking to do:
Upload an entire form of data, one piece of which is a single file
Work with Codeigniter's file upload library
Up until here, all is well. The data gets in my database as I need it. But I'd also like to submit my form via an AJAX post:
Using the native HTML5 File API, not flash or an iframe solution
Preferably interfacing with the low-level .ajax() jQuery method
I think I could imagine how to do this by auto-uploading the file when the field's value changes using pure javascript, but I'd rather do it all in one fell swoop on for submit in jQuery. I'm thinking it's not possible to do via query strings as I need to pass the entire file object, but I'm a little lost on what to do at this point.
Can this be achieved?
It's not too hard. Firstly, take a look at FileReader Interface.
So, when the form is submitted, catch the submission process and
var file = document.getElementById('fileBox').files[0]; //Files[0] = 1st file
var reader = new FileReader();
reader.readAsText(file, 'UTF-8');
reader.onload = shipOff;
//reader.onloadstart = ...
//reader.onprogress = ... <-- Allows you to update a progress bar.
//reader.onabort = ...
//reader.onerror = ...
//reader.onloadend = ...
function shipOff(event) {
var result = event.target.result;
var fileName = document.getElementById('fileBox').files[0].name; //Should be 'picture.jpg'
$.post('/myscript.php', { data: result, name: fileName }, continueSubmission);
}
Then, on the server side (i.e. myscript.php):
$data = $_POST['data'];
$fileName = $_POST['name'];
$serverFile = time().$fileName;
$fp = fopen('/uploads/'.$serverFile,'w'); //Prepends timestamp to prevent overwriting
fwrite($fp, $data);
fclose($fp);
$returnData = array( "serverFile" => $serverFile );
echo json_encode($returnData);
Or something like it. I may be mistaken (and if I am, please, correct me), but this should store the file as something like 1287916771myPicture.jpg in /uploads/ on your server, and respond with a JSON variable (to a continueSubmission() function) containing the fileName on the server.
Check out fwrite() and jQuery.post().
On the above page it details how to use readAsBinaryString(), readAsDataUrl(), and readAsArrayBuffer() for your other needs (e.g. images, videos, etc).
With jQuery (and without FormData API) you can use something like this:
function readFile(file){
var loader = new FileReader();
var def = $.Deferred(), promise = def.promise();
//--- provide classic deferred interface
loader.onload = function (e) { def.resolve(e.target.result); };
loader.onprogress = loader.onloadstart = function (e) { def.notify(e); };
loader.onerror = loader.onabort = function (e) { def.reject(e); };
promise.abort = function () { return loader.abort.apply(loader, arguments); };
loader.readAsBinaryString(file);
return promise;
}
function upload(url, data){
var def = $.Deferred(), promise = def.promise();
var mul = buildMultipart(data);
var req = $.ajax({
url: url,
data: mul.data,
processData: false,
type: "post",
async: true,
contentType: "multipart/form-data; boundary="+mul.bound,
xhr: function() {
var xhr = jQuery.ajaxSettings.xhr();
if (xhr.upload) {
xhr.upload.addEventListener('progress', function(event) {
var percent = 0;
var position = event.loaded || event.position; /*event.position is deprecated*/
var total = event.total;
if (event.lengthComputable) {
percent = Math.ceil(position / total * 100);
def.notify(percent);
}
}, false);
}
return xhr;
}
});
req.done(function(){ def.resolve.apply(def, arguments); })
.fail(function(){ def.reject.apply(def, arguments); });
promise.abort = function(){ return req.abort.apply(req, arguments); }
return promise;
}
var buildMultipart = function(data){
var key, crunks = [], bound = false;
while (!bound) {
bound = $.md5 ? $.md5(new Date().valueOf()) : (new Date().valueOf());
for (key in data) if (~data[key].indexOf(bound)) { bound = false; continue; }
}
for (var key = 0, l = data.length; key < l; key++){
if (typeof(data[key].value) !== "string") {
crunks.push("--"+bound+"\r\n"+
"Content-Disposition: form-data; name=\""+data[key].name+"\"; filename=\""+data[key].value[1]+"\"\r\n"+
"Content-Type: application/octet-stream\r\n"+
"Content-Transfer-Encoding: binary\r\n\r\n"+
data[key].value[0]);
}else{
crunks.push("--"+bound+"\r\n"+
"Content-Disposition: form-data; name=\""+data[key].name+"\"\r\n\r\n"+
data[key].value);
}
}
return {
bound: bound,
data: crunks.join("\r\n")+"\r\n--"+bound+"--"
};
};
//----------
//---------- On submit form:
var form = $("form");
var $file = form.find("#file");
readFile($file[0].files[0]).done(function(fileData){
var formData = form.find(":input:not('#file')").serializeArray();
formData.file = [fileData, $file[0].files[0].name];
upload(form.attr("action"), formData).done(function(){ alert("successfully uploaded!"); });
});
With FormData API you just have to add all fields of your form to FormData object and send it via $.ajax({ url: url, data: formData, processData: false, contentType: false, type:"POST"})
I would like to know the best way to send this array of favorites to php, Im trying to use ajax, but I keep getting a 403 forbidden error. The path is correct, I must be doing something wrong here, any help would be greatly appreciated.
$(function(){
var favorite = localStorage.getItem( 'favorite' );
if (favorite !== null){
favorite = JSON.parse(favorite) || [];
}
$('.favorites' ).each(function() {
var petid = $(this).attr('data-petid');
if(favorite.indexOf(petid) !== -1){
$(this).css('background-image', 'url(../assets/img/heart-red.svg)');
$(this).css('background-color', '#fefefe');
}
});
// This function changes the color of the heart on the landing page and stores the values into local storage
$(".favorites").click(function() {
var favorite = localStorage.getItem( 'favorite' );
var petid = $(this).attr('data-petid');
var index;
favorite = JSON.parse(favorite) || [];
if ((index = favorite.indexOf(petid)) === -1) {
favorite.push(petid);
$(this).css('background-image', 'url(../assets/img/heart-red.svg)');
$(this).css('background-color', '#fefefe');
}else {
$(this).css('background-image', 'url(../assets/img/heart-full.svg)');
$(this).css('background-color', '#25aae3');
favorite.splice(index, 1);
}
localStorage.setItem('favorite', JSON.stringify(favorite) );
$.ajax({
type: "POST",
url: '/petlist/fuel/app/views/site/favorites.php',
data: favorite,
success: function(response){
console.log(response);
}
});
});
});
For ajax calls in Fuel, use a controller that extends Controller_Rest
Your ajax request should look like this.
$.post('/petlist/fuel/app/views/site/favorites.php', { "favorite" : favorite }, function(data) {
console.log(data);
});
Then in PHP, you can access the data via
print_r($_POST['favorite']);
I have a form that is a drop down select list.
I also have an action, that looks for the request parameter:
indexAction:
if($this->getRequest()->isXmlHttpRequest())
{
$this->setLayout('layout');
}
$param = $this->getRequestParameter('type');
if($param == 'video')
{
isicsBreadcrumbs::getInstance()->addItem('All Videos', '#homepage');
$pager = new sfPropelPager('Item', 15);
$pager->setPage($request->getParameter('page', 1));
$pager->setPeerMethod('doSelectLatestVideo');
$pager->init();
$this->pager = $pager;
}
elseif($param == 'photo')
{
isicsBreadcrumbs::getInstance()->addItem('All Photos', '#homepage');
$pager = new sfPropelPager('Item', 15);
$pager->setPage($request->getParameter('page', 1));
$pager->setPeerMethod('doSelectLatestPhoto');
$pager->init();
$this->pager = $pager;
}
}
Now this works fine when the url is: example.com?type=video - it loads the video content
The problem is, I'm wanting to update the content using AJAX and because I'm doing it via AJAX, I'm struggling to get the requestParamater, since it is no longer in mu URL;
ajax function:
$("#filter-form-newsroom .submit").live('click', function(e){
$("#search-results").html(ajax_loading);
var content_type = $("#filter-form-newsroom #type").val();
$.ajax(
{
url: "",
type: "GET",
data: "?type=" + content_type,
success: function(data){
var $response=$(data);
var filtered_response = $response.find('.post');
$("#search-results").html(filtered_response).hide().fadeIn("fast");
}
});
e.preventDefault();
});
This function checks the parameter in my select list and is supposed to filter by the requestParamter, but it isn't working.
Any ideas?
Thanks
Rather than putting ?type=" into the data property, put it in the url. Wouldn't that result in the same request you get when you type the URL yourself?