ajax request php class function - url

i have content listed in a div and i have a dropdown with various options to order and filter that content.
I'm using ajax to filter/order that content and is working but i use other php page with the content i want on the div that has the content, like this
function order(str){
$.post("order_products.php",
{
q: str,
},
function(data, status){
document.getElementById("txtHint").innerHTML = data;
});
}
What i wanted was to instead of putting the code (data) to change in another page just for that, i could put that code inside a class php function that i have.
<?php
class products{
function list(){
blablabla
}
That way i would "save space" and organize everything, considering that i have many other things to order/filter but i don't know to to make the ajax request to that function, or if it's possible without having a page in between and then get the response from the function and put it on the div.

You can do this using Laravel by setting up a route to a function that will do the ordering. Please note I've made a lot of assumptions in the following answer as I can't see all your code and have made it quite general, please adjust the code to your project or provide more details of your code if you don't understand the answer fully.
routes.php
Route::post('products/order', [
'as' => 'products.order',
'uses' => 'ProductsController#orderProducts'
]);
Your view (assuming you're using blade)
$txtHint = $('#txtHint'); // grab the reference to txtHint dropdown
$.post( '{{ route("products.order") }}', // hit our route
{
q: str,
},
function(data, status){
$txtHint.empty(); // clear the dropdown
// loop through the data and assign each element to the dropdown
$.each(data, function(value, key) {
$txtHint.append($("<option></option>")
.attr("value", value)
.text(key));
});
});
ProductsController.php
public function orderProducts()
{
$orderBy = \Input::get('q');
return \Products::lists('name', 'id')->orderBy($orderBy);
}
For outside of a framework just change the url to your php file and add in a data attribute for the method you require to be fired from the file.
$.post( 'products.php', // hit our route
{
action: 'order',
q: str,
},
...
Then in products.php you'd do something like this
if(isset($_POST['action']) && !empty($_POST['action'])) {
$action = $_POST['action'];
switch($action) {
case 'order' : order();break;
case 'otherFunction' : otherFunction();break;
}
}
function order()
{
// order logic here
// get $_POST['q']
// do your ordering
// return data as json
}
See here for similar question: using jquery $.ajax to call a PHP function

Related

Updating list in view Asp.net mvc razor

I have 2 lists in a view. What I want to do is that pick elements from list1 and update list2 with selected elements everytime I pick one. I tried to use PartialView (I don't know if it's correct approach or not) but I failed. I have a function in controller that fills a list by selected items. What needs to be done is updating the view dynamically. Can you suggest me a roadmap for this?
Update
I forgot to say that I have done this with javascript. But I feel like it's the long way when it comes to some validations (checking duplications etc.)
$(document).ready(function (){
$("#allPlayersList a").on("click", function () {
var options = $(this).clone();
$("#thisWeekList").append(options);
});
});
Just create an html list. See if this link helps. https://codepen.io/alexander-holman/pen/QNQrvz. You can also populate the values from database
Then you can get the selected element by javascript like this
var input = document.getElementById('Something').value;
Update after edited question
You can try something like
var listSelection = document.getElementById('Something').value;
Now you can create an api in the backend which accepts this value and returns a list based on it. Call that Api like this
&.ajax({
url: //url of api
data: {exactNameOfApiParameter : listSelection },
success: function(data){
for (i = 0; i < data.length; i++) {
$('<li>', { text: data[i] }).appendTo($('#list2'));
}
}
})
Make sure that id of second list is list2.

Select2 use a dynamic Ajax URL on call

I use the Select2 plugin (v 3.5.2) with Ajax to dynamically load elements in the list.
I have an issue as between the initialization of the Select2 (where a url property is set in the ajax helper) and the time the ajax call is made, this url might need to be changed.
So I have something like this :
$box.select2({
containerCssClass: "form-control"
minimumInputLength: 0,
allowClear: true,
ajax: {
url: someUrl,
dataType: 'json',
quietMillis: 100,
...
}
I can't figure out how, when, where to change the ajax.url value before it launches.
The help of Select2 says:
Select2 uses jQuery's $.ajax function to execute the remote call by default. An alternative transport function can be specified in the ajax settings, or an entirely custom implementation can be built by providing a custom query function instead of using the ajax helper.
But I can't find any example on how to do it.
Thanks in advance for any help. Much appreciated.
I can't figure out how, when, where to change the ajax.url value before it launches.
The ajax.url option can be specified as a static string or a method returning one in both Select2 3.5.x and 4.0.0.
$("select").select2({
ajax: {
url: function () {
return UrlHelper.RemoteAPI();
}
}
});
This is useful for changing the base URL, for example when the URL is determined at runtime or is automatically generated in a different method. If you need to change the query parameters, such as the one used for sending the search term, you need to override the ajax.data option.
$("select").select2({
ajax: {
data: function (args) {
// args is the search term in 3.5.x
// args is an object containing the query parameters in 4.0.0
// args.term is the search term in 4.0.0
return {
search: args.term || args;
};
}
}
});
The data here will be appended as query parameters by default, and will be sent as the request body if the method type is changed from GET (the default) to anything else.
Select2 uses jQuery's $.ajax function to execute the remote call by default. An alternative transport function can be specified in the ajax settings, or an entirely custom implementation can be built by providing a custom query function instead of using the ajax helper.
But I can't find any example on how to do it.
Select2 does allow for a different AJAX transport to be used by changing the ajax.transport option.
In 3.5.2, this must be a $.ajax-compatible method, so it must be able to take an object containing the success and failure callbacks.
$("select").select2({
ajax: {
transport: function (args) {
// args.success is a callback
// args.failure is a callback
// should return an object which has an `abort` method.
return $.ajax(args);
}
}
});
In 4.0.0, this must be a method which takes a params object (the same one passed to ajax.data), a success callback, and a failure callback.
$("select").select2({
ajax: {
transport: function (params, success, failure) {
var $request = $.ajax(params);
$request.then(success);
$request.fail(failure);
return $request;
}
}
});
Very Simple Javascript code to handle the same, can be used in Suitescript(Netsuite) also.
// prepare your dynamic URL inside this method and return
function getURL() {
return url + params;
}
// While binding the select2 with the dropdown set url to call a anonymous function which internally calls another function.
jQuery("select.itemDropDown").select2({
placeholder: "Select an item",
width: "200px",
minimumInputLength: 3,
ajax: {
url: function() {
return getURL()
},
dataType: 'json'
}
});

Callback after .swap() not working - ASP.NET SPA w/sammy.js

I am building a Single Page Application using ASP.NET and sammy.js, where all views except for the Home/Index view are rendered as partial views so that sammy can swap out the content of the main body with the partial view that is returned.
I am using the example given here, and everything loads fine as expected.
Similar to the above example, in my Home/Index page I have reference to a script called routing.js, which wraps the sammy function call in order to parse the MVC route:
var Routing = function (appRoot, contentSelector, defaultRoute) {
function getUrlFromHash(hash) {
var url = hash.replace('#/', '');
if (url === appRoot)
url = defaultRoute;
return url;
}
return {
init: function () {
Sammy(contentSelector, function () {
this.get(/\#\/(.*)/, function (context) {
var url = getUrlFromHash(context.path);
context.load(url).swap();
});
}).run('#/');
}
};
}
I need to call a callback function after the content swap has fully completed in order to implement further jQuery functionality on the newly rendered content. My dilemma is that no matter what option I try from the sammy.js docs, nothing seems to run the callback after the content has been swapped.
I have tried all of the following (all "valid" ways of passing a callback according to the sammy.js docs):
content.load(url).swap(pageLoadScripts(url));
content.load(url).swap().onComplete(pageLoadScripts(url));
content.load(url).swap().then(pageLoadScripts(url));
content.load(url).swap().next(pageLoadScripts(url));
content.load(url,pageLoadScripts(url)).swap();
and even
content.load(url).swap();
pageLoadScripts(url);
In every case the pageLoadScripts function fires off prior to the content being swapped. Any ideas or suggestions on what to do differently?
This is a bit of a hack, but it works.
Inside the Sammy initialization function, I added the following override to the swap function just before the override to the get function:
this.swap = function (content, callback) {
var context = this;
context.$element().html(content);
pageLoadScripts(hashedUrl);
};
FWIW, I still have not been able to get callback to be anything other than 'undefined', even in this override function.
Managed to get this working:
// override for callback after page load
this.swap = function(content, callback) {
this.$element().html(content);
if (callback) {
callback();
}
};
// users
this.get('/#/users', function(context) {
context.load('/users').swap(function() { replaceBindings(viewModel.users); });
});
I managed to get the callback param to NOT be 'undefined' by wrapping it in another function.

How to create a 'url_for' link helper in AngularjJS

In .NET MVC there is #Url.Action() and in RoR there is url_for()
I could not find similar url building helper in angularjs.
I'm already providing everything that is needed to build url to $routeProvider so something like: $routeProvider.urlFor("MyCtrl", {id: 5}) could be nice to have.
My main goal here is to avoid hardcoded urls in viewes and other places and to avoid repeating url/routes patterns twice.
UPDATE:
Seems like it's hard to explain what i want so here is exact example of what i want:
Instead of writing this in viewes:
<a ng-href="/product/5">foo</a>
I want to write this:
<a ng-href="urlFor("ProductCtrl", {id:5})">foo</a>
So if later i decide to change path of ProductCtrl I would not have to update url in this a element.
What would be good solution for my goals?
You could try with something like the following (just came up with it) inside your main module's run() block:
app.run(function($route, $rootScope)
{
$rootScope.path = function(controller, params)
{
// Iterate over all available routes
for(var path in $route.routes)
{
var pathController = $route.routes[path].controller;
if(pathController == controller) // Route found
{
var result = path;
// Construct the path with given parameters in it
for(var param in params)
{
result = result.replace(':' + param, params[param]);
}
return result;
}
}
// No such controller in route definitions
return undefined;
};
});
This will extend the root scope of the application with the new path() function - so it can be used anywhere in the application. It uses the $route service to get the controller names and the corresponding paths, so you won't have to repeat yourself.
Example usage:
{{ path('LibraryController', { bookId : 'x', chapterId : 'y' }) }}
Live example at: http://plnkr.co/edit/54DfhPK2ZDr9keCZFPhk?p=preview
There are numerous approaches...a custom directive or ng-click to modify $location, or using a function in ng-href to parse the url from object and have it placed as href in an <a> tag.
Example using ng-href:
HTML:
<li ng-repeat="item in items">
<a ng-href="{{url(item)}}">{{item.txt}}</a>
</li>
JS:
function Ctrl($scope){
$scope.items=[
{id:1,txt:'foo'},
{id:2,txt:'bar'}
];
$scope.url=function(item){
return '#/'+item.id
}
}
Example using ng-click and $location
HTML:
<a ng-click="newPath(item)">{{item.txt}}</a>
JS:
function Ctrl($scope){
$scope.items=[
{id:1,txt:'foo'},
{id:2,txt:'bar'}
];
$scope.newPath=function(item){
$location.path('/'+item.id)
}
}
DEMO: http://jsbin.com/ovemaq/3
In one of recent project I came up to this solution it helped me to solve my needs right in time. It will be interesting to help you to improve it to fit your usecase.
1. Move routes definition to config:
...
ROUTES: {
PAGE1: '/page1/:id',
PAGE2: '/page2/:id/:name'
},
...
2. Define routes, using values from config:
app.config(['$routeProvider', 'config', function ($routeProvider, config) {
$routeProvider.when('/', {
templateUrl: 'partials/home.html',
controller: 'HomeCtrl'
});
$routeProvider.when(config.ROUTES.PAGE1, {
templateUrl: 'partials/page1.html',
controller: 'PageOneCtrl'
});
...
$routeProvider.otherwise({
redirectTo: '/'
});
}]);
3. Set up service to provide functionality to create urls:
services.factory('routes', function (config) {
// populates `:param` placeholder in string with hash value
var parseString = function (string, parameters) {
if (!string) return '';
if (!parameters) return string;
for (var index in parameters) {
if (!parameters.hasOwnProperty(index)) continue;
string = string.replace(':' + index, parameters[index]);
}
return string;
};
return {
getPage1Link: function (urlParams) {
return '#' + parseString(config.ROUTES.PAGE1, urlParams);
}
};
});
== Drawbacks ==
With this approach I had to define getter for each route (there were less then 5, and development speed was vital)
It appears that what you want is the ui-route directive which has just been recently added to the angularui project. There is a nice set of out-of-the-box options.

Post multiple parameters to MVC Controller using jQuery.post

I have a controller defined as:
[AcceptVerbs(HttpVerbs.Post)]
public JsonResult PostMoreData(DataContracts.Address address, DataContracts.GeoLocation geoLocation)
{
return Json("test");
}
where DataContracts.Address and DataContracts.GeoLocation are complex types.
From my View i'm trying to post using jQuery as such:
function PostMoreData() {
var JsonAddress = {
"Building": $('Building').val(),
"UnitNumber": $('UnitNumber').val(),
"StreetNumber": $('StreetNumber').val(),
"StreetName": $('StreetName').val(),
"StreetType": $('StreetType').val(),
"Suburb": $('Suburb').val(),
"State": $('State').val(),
"Postcode": $('Postcode').val(),
"MonthsAtAddress": $('MonthsAtAddress').val()
};
var JsonGeoLocation = {
"Latitude": $('Latitude').val(),
"Longitude": $('Longitude').val()
};
jQuery.post("/AddressValidation/PostMoreData", {address: JsonAddress, geoLocation: JsonGeoLocation}, function(data, textStatus) {
if (textStatus == "success") {
var result = eval(data);
if (result.length > 0) {
alert(result);
}
}
}, "json");
}
However, on the controller, I get nulls.
It works if my Controller takes just 1 argument and I post just one object.
[AcceptVerbs(HttpVerbs.Post)]
public JsonResult PostMoreData(DataContracts.Address address)
{
return Json("test");
}
function PostMoreData() {
var JsonAddress = {
"Building": $('Building').val(),
"UnitNumber": $('UnitNumber').val(),
"StreetNumber": $('StreetNumber').val(),
"StreetName": $('StreetName').val(),
"StreetType": $('StreetType').val(),
"Suburb": $('Suburb').val(),
"State": $('State').val(),
"Postcode": $('Postcode').val(),
"MonthsAtAddress": $('MonthsAtAddress').val()
};
jQuery.post("/AddressValidation/PostMoreData", JsonAddress, function(data, textStatus) {
if (textStatus == "success") {
var result = eval(data);
if (result.length > 0) {
alert(result);
}
}
}, "json");
}
Any ideas how i can post more than one object?
Note that the "default serialization" that jQuery is doing here isn't going to work no matter what your controller does. jQuery doesn't "traverse" the parameter map below the first level, so the example in the question is likely generating this post data:
address=[object]&geoLocation=[object]
The other, working example does not contain any sub-objects, so it is being translated directly, like this:
Building=value&UnitNumber=value&...&MonthsAtAddress=value
The easiest fix is making the parameter map flat, each key prefixed with either 'Address.' or 'GeoLocation.', depending.
Thank you everyone for your input on this issue.
At this stage, we have departed from using jquery to post complex types to controllers. Instead we use the ms ajax framework to do that. ms ajax post nicely binds the complex types automatically out of the box.
So our solution now uses a mix of jquery and ms ajax framework.
Ash
Your code requires that the way jquery serializes an object is compatible with the MVC default model binder, which I think is unlikely.
If you can build your javascript object so that it serializes as a flat object with dot notation (JsonAddress.Building) that would work, or you can let jquery do the default serialization and then create a custom model binder to deserialize to the action parameter types.
I had the same problem and couldn't get anything to work. Also someone raised it as a bug with jquery and they closed it as not a bug.
I have found a few solutions which answer part of the whole question.
And the answer includes the following.
1) Client side: we would need to stringyfy all the objects you need to send. This could be a normal object or an array. It works on both.
2) Client side: You send the data as you have in the first post. As you would object by object.
Tip: When you send parameterised objects, jquery encodes the data sent to the server.
Following all are server side implementations
1) Deserializer class: which will take the input string and put it back in to object/list<>/IList<> what ever you have defined as datatype of the parameter of the controller function.
You would need to implement ActionFilterAttribute for the above.
2) Finally add an attribute to controller function, so that it uses the deserialiser class to get the parameters.
As this is quite a lot of code let me know if you need details or have you solved the problem.
Deepak Chawla

Resources