Image a page, that page is called "dashboard". In the dashboard, there is a drop-down menu, with items, which are listed by the PHP script, and their count varies on the number of results from a database.
Now, when a user clicks one of the items from the menu, it should redirect him to the configuration page, with some data (id, type). Sounds simple, but the redirecting method used is made with angular, so it uses URL hashing, without refreshing the site. URL of configuration page then looks like:
https://www.example.com/index.php#/configure
...and I want to get there some data. The site we see there is just a blank site, which, in the file tree, is named "configuration.php", but you don't see it in the URL, because of angular code in "configure.module.js.php", which simply redirects the user, gives them the right site with:
(function () {
'use strict';
angular.module('BlurAdmin.pages.configure', [])
.config(routeConfig);
/** #ngInject */
function routeConfig($stateProvider) {
$stateProvider
.state('configure', {
url: '/configure',
title: 'Configuration',
templateUrl: 'app/pages/configure/configure.php',
controller: 'addCtrl',
});
}
})();
So I assume, that if I want to get the data to my site, I need some kind of a GET request. I figured out, that it will work if I use the GET request like so:
https://www.example.com/index.php?something=works&omg=itWorks#/configure
So my index.php will work with the GET data and write them to a SESSION, which can then be used in configuration.php!
Well, it works, kinda... But the main thing is, that it is all angular, so NO SITE REFRESH AT ALL! That means none of my files will be refreshed, so after I click the button again, the site will not get the GET request again, it will simply redirect me to configuration.php, without dealing with the new data... It will keep the first GET parameters and SESSION.
So there goes my question. how to make it? I really need that one click to send that data to configuration.php, without refreshing the site, but, working and updating.
In html you add ui-sref to like this
ui-sref="configure/({id: valueid})
in file config
url:'/configure/:id'
in your controller add $stateParams like this
function addCtrl($scope,$http,$stateParams)
and use ajax to GET
var params = $.param({'id':$stateParams.id})
$http({
method:'GET',
url:'yoururl?id=' + $stateParams.id,
data:params,
headers : { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(onSuccess);
Related
Am playing with Framework7 to do hybrid mobile app development. I have three tabs (bottom fixed), which are Home, Contacts and Settings/Profile
My app.js file looks somewhat like this:
var $$ = Dom7;
var app = new Framework7({
//.....
data: function () {
return {
user_profile : ''
}
},
on: {
tabShow( tab ) //-- when a bottom tab is clicked
{
if( $$(tab).attr('id') == 'view-settings' )
{
//.. do ajax call and get the response data in "resp"
app.data.user_profile = resp.response.profile; //setting the info to app's data
}
}
},
routes: routes
});
var settingsView = app.views.create('#view-settings', {
url: '/settings/'
});
And in routes.js:
routes = [
{
path: '/',
url: './index.html',
},
{
path: '/contacts/',
componentUrl: './pages/contacts.html',
},
{
path: '/settings/',
componentUrl: './pages/settings.html',
}
];
This Contacts page contains static content. For the Home page, am doing the AJAX API call during the deviceready state. Because am setting up some headers for authentication and stuff(for all the AJAX api calls) in there.
The problem am facing is, am unable to display the content in Settings page. It is always empty!
Am using this in that template page:
<div class="item-title item-label">Full Name - {{$root.user_profile.full_name}}</div>
I want to compile that template only when clicking the respective tab button.
Maybe that's the problem.
Any suggestions?
After going through the documentations again and again, I got another way to do this.
So, during the tabShow event, I check whether the user is accessing the Settings/Profile tab. If so, I check whether an object in app.data (eg: app.data.user_profile is empty or not(am storing the profile details there). If empty, I would do an AJAX API call to get the profile details. When the profile details is obtained, I would use app.form.fillFromData() method to fill the form. Documentation here: https://framework7.io/docs/form.html#form-data-app-methods
Make sure to name the form as well as the input elements in that form, and the same name should be use in the object(key name) when calling the fillFromData() function.
And one more thing, for the routes, /settings/ path, I used url instead of the componentUrl property to pass the url of the page.
This may not be the best solution, but am still learning. And it seems to have solved by current problem.
Thank you
I'm still relatively new to AngularJS so bear with me on this one. I'm trying to create a photo-liking system and when the user clicks the like button, it increases the number of likes. I have this functionality down, but the only thing is that I have to reload the page in order for the "like" to show. This means that everything on the backend is in order. However, I would like to prevent having to do reload the page.
One thing to note is that I have a partial template, and a HTTP post request occurs once the button is clicked with an ng-click directive.
HTML SNIPPET FROM PARTIAL TEMPLATE
<a class="like" ng-click="likeIt(//PHPCODEGOESHERE//)">Like</a>
AngularJS
userApp.controller('photoController',['$scope','$location','$window','$log','$route','$routeParams','$location','$http', function($scope,$location,$window,$log,$route,$routeParams,$location,$http){
$scope.name = 'Photos';
$scope.likeIt = function(parameters){
$http.post('centralcommand.php', {id: parameters}).success(function(data,status,headers,config){
window.location.reload(); // Causes page to reload
}).error(function(data,status,headers,config){
alert('failure');
});
};
}]);
Please also note that I have tried to change the innerHTML in the success callback. This doesn't work because I already am mixing PHP with HTML and I have to use both ' and " in the HTML code so when I get the HTML text and replace it using innerHTML it doesn't work correctly.
I was able to find an answer after perusing a different method and it comes from this answer provided in a separate StackOverflow post. It has to do with reloading the template cache using the $templateCache service:
userApp.controller('photoController',['$scope','$location','$window','$log','$route','$routeParams','$location','$http','$templateCache', function($scope,$location,$window,$log,$route,$routeParams,$location,$http,$templateCache){
$scope.name = 'Photos';
var currentPageTemplate = $route.current.templateUrl; // ADDITION # 1
$scope.routeReloader = function(parameters){
$http.post('centralcommand.php', {id: parameters}).success(function(data,status,headers,config){
$templateCache.remove(currentPageTemplate); // ADDITION # 2
$route.reload(); // ADDITION # 3
}).error(function(data,status,headers,config){
alert('failure');
});
};
}]);
This is my first post of stackoverflow. I've spent the past month trying to solve this on my own, extensively searching Google and this website. Here's my problem:
I have a website where users can search for cases. When they find a case, their results are loaded on a case details page. Users normally search for cases from the homepage by clicking a search option, where they enter a case number like the following:
14-12345
Users submit their search to the homepage's index controller. The controller parses the search and redirects to a "case" action. This action polls the database to get case details, and returns a case view.
This search works - users see the results of their search on a case details page. However, a request was received so users can search for cases from the case details page as well.
I can't make the new request work. I've tried using Web API (which really became a waste of time, because I want to return a whole view, not just search data), and I've failed to create the appropriate controller/view combination to work with my data. I usually wind up trying to use the existing controller (which has the code to search) and the case details view.
Breaking down the pieces...
The model data is stored in a viewmodel file:
public class PortalCaseView
{
public DocketCase CaseInfo { get; set; }
public List<CaseNote> Notes { get; set; }
public string Search { get; set; }
...other various variable declarations, etc
}
The Index.cshtml file is the homepage/main landing page for the site. Users can search for case details by going to a section to search (code from the view here):
<div class="tile">
<span>Search by Case Number</span>
#Html.EditorFor(x => x.Search)
<a class="m-btn green-stripe" href="javascript:submitForm();" style="color: #444;
text-decoration: none;">Submit<i class="icon-hdd"></i></a> <a class="m-btn red-stripe"
href="javascript:toggleSearch();" style="color: #444; text-decoration: none;">Cancel<i
class="icon-remove"></i></a>
</div>
(Submitting the result gives a submit command, which posts the search to the controller.)
The PortalController.cs controller file directs requests for the homepage. Its Index method grabs the Search variable, and redirects to a Case action to process:
Index
if (!string.IsNullOrWhiteSpace(viewmodel.Search))
{
...
return RedirectToAction("Case", new { Year = docketnumber[0], Sequence = docketnumber[1], J = viewmodel.JudgeCode });
}
Case
[HttpGet]
public ActionResult Case(int Year, int Sequence, string J)
{
...various declarations and requests to get db information...
return View(vm); //vm is a viewmodel with info for the case view
}
[HttpPost]
public ActionResult Case(PortalCaseView vm)
{
return View(vm);
}
* When the redirect to the Case action is complete, the Case.cshtml view loads with the necessary details. Now that searches from the case view are required, I've added a section to the case view to take an "on-demand" search query:
<textarea id="searchForCase" style="width: 150px;"></textarea>
<a class="m-btn green-stripe" href="javascript:searchCase();" style="color: #444;
text-decoration: none;">Search<i class="icon-hdd"></i></a>
And here is where problems start. During a typical run, Ajax/JSON code builds a call back to a controller action. Then, the action executes (usually on data stored in a file or folder). A view is returned, and then the page refreshes. (This is when a user is using the site.) It doesn't work the same way for my new custom code.
My custom searchCase() function takes the case number entered by a user to search for it (it goes back to the Index action in the original PortalController.cs file):
var searchCase = function () {
var textArea = document.getElementById("searchForCase");
var txt = String(textArea.value);
jQuery.ajax({
type: "POST",
url: "#Url.Action("Index","Portal")",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ fromCaseSearch: txt }),
success: function (data) {
alert(data);
},
failure: function (errMsg) {
alert(errMsg);
}
});
$('form').submit();
}
(Note: I've already tried changing the datatype from json to html; I'm assuming I might need to work with the content type)
I've traced the progress from this point. The website goes back to PortalController.cs and to the Index action (following through like a good POST), and then takes the search query provided by the user. Since it falls out of the Index action when I try to redirect to the Case action like before, I added an if statement to deal with search queries directly from the case details view:
if (!string.IsNullOrEmpty(fromCaseSearch))
{
System.Web.HttpContext.Current.Session.Clear();
//forget why I put that clear request there, but I do
//use session state variables, so I might need to clear
//them when searching from scratch - if they exist
viewmodel = new PortalIndexView();
viewmodel.Search = fromCaseSearch;
...initialization and parsing for search...
...searching for and loading data from database(s)...
ModelState.Clear(); //was hoping this would "refresh" view
//...this didn't work either
return View("Case", vm); //forced website to return
//case view with viewmodel data
//...this actually starts loading
//the case view
}
This actually works... to a point. The data gets processed the same way, and the case view is loaded like normal. However, even after tracing the loading process (and seeing that model variables are sent to the view), the page does not update with the new information).
So, that's where I'm stuck. I've tried tweaking some settings (and even thought the problem might be in the web.config file), but when I run across problems like this, what usually fixes the problem for me is to find out what I did wrong here (or in the general vicinity of the problem - the answers usually happen when I fix simple stuff first).
Some last-minute things:
PortalController.cs (the controller) outputs to Case.cshtml (the case details view). When right-clicking the View controller action, it redirects back to PortalController.cs (the main controller from the landing page).
No other controller shares Case.cshtml.
There is no CaseController.cs file. It looks like my predecessor simply created the search "redirect", figuring users would only search from the homepage (and they did up until now).
Last-second idea? Maybe I'm supposed to account for HTTPGet and HTTPPost actions for my new code as well. Not sure... brain is mush...
Naturally, since this is a work project, I can only provide so many details, but I'll be glad to take suggestions at this point.
UPDATE: is it possible that my problem is because I didn't include a #using (Html.BeginForm(...)) line in my case details view? I noticed there isn't one. Do you need one to be able to have official POST action in the related controller?
One other clarification: I'm using Ajax/JSON for passing data back to the controller from the case view, since I can't get the page to just "submit" (in Javascript/JQuery code, $('form').submit() does not work at all). I'm wondering if it has anything to do with Web API. (There is a Web API file called CaseNoteController.cs that handles notes that get added to cases. When I was trying to work with Web API - and possibly return a view using it - I had a test api call that made the case details view page refresh effortlessly; I just couldn't figure out how to get it to work for my needs.)
Problem solved (my fault). My lack of experience kept me from figuring this out sooner:
I wound up not needing the searchCase function in the Case view. The reason why: I didn't wrap my Case view in a #using(Html.BeginForm()) code block, which meant that my page wasn't posting results (no matter how hard I tried)
I didn't pay attention to my PortalController.cs file, which already had HttpGet and HttpPost variants of my Case action. (The HttpPost action was completely empty, save for returning a view. That explains why the page failed to load and display anything, let alone the results of my next case search.)
Once I corrected those issues (and tweaked a few other buttons so they didn't automatically post or try to run when I submitted the document), the code finally worked! Praise God. No need for convoluted or weird paths back to the controller - things happened real quick after that.
(Now to trim off a whole bunch of scaffolding and otherwise unnecessary code...)
In my AngularJS app, I have a route that looks like:
.when('/:project/:page', {
templateUrl: '/ui-editor/editor',
controller: 'EditorCtrl'
})
In a view, I have a link that looks like:
Next page
When I click that link in my app, the URL in the browser changes correctly (e.g. /myproject/1 to /myproject/2), but I get an error Error: [ng:areq] Argument 'scope' is required. The line that the error refers to is the console.log statement in:
socket.on('ws:init-data', function(data) {
console.log('on ws:init-data', data);
// Handle incoming data from server
//...
});
If I refresh my browser, the correct data loads as it should for /myproject/2.
use ng-href is better. It can avoid link be clicked before angular parse.
<a ng-href="/{{currentProjectId}}/{{currentPageId + 1}}">Next page</a>
I don't know the exact cause about this error, but I have a suggestion:
use $location to change your url.
you can see on the dev_guide:
When should I use $location?
Any time your application needs to react to a change in the current URL or if you want to change the current URL in the browser.
http://docs.angularjs.org/guide/dev_guide.services.$location
I am trying to implement a search function for my website. When the user types a search term foobar into a input box and submits it, he is redirected to http://mydomain.com/search?query=foobar.
Problem:: How should I grab the GET parameters query from the URL, and send it to the backend and get a array of results back as a JSON response? Should I even do it this way?
My current attempt below does not even cause the search function to be triggered.
Router
var AppRouter = Backbone.Router.extend({
routes: {
'search?query=:query': 'search'
// ... and some other routes
},
search: function(query) {
this.photoList = new SearchCollection();
var self = this;
this.photoList.fetch({
data: {query: query},
success: function() {
self.photoListView = new PhotoListView({ collection: self.photoList });
self.photoListView.render();
}
});
}
});
var app = new AppRouter();
Backbone.history.start({
pushState: true,
root: '/'
});
There have been several issues filed against Backbone for this very issue. There is an existing plugin that works well for this:
https://github.com/jhudson8/backbone-query-parameters
Alternatively, I'm currently using query string parameters in a mock API that matches Backbone's route matching. Looks something like this
Route
"/api/v2/application/:query"
Query
application: function(query) {
var params = $.deparam(query.slice(1));
// params.something...
}
As to your actual issue at hand how are you redirecting to index.html to support pushState?
I hit this same issue and contemplated using backbone-query-parameters, but that should be considered generally an incorrect approach.
The url query string is not meant for the front end. They get sent to the server and force a refresh when navigating from page.html to page.html?something=something.
You should be using hash fragments instead. i.e. http://www.example.com/ajax.html#key1=value1&key2=value2 then just get those values the normal backbone way and build your request params from that.
See https://github.com/jashkenas/backbone/issues/891, https://developers.google.com/webmasters/ajax-crawling/docs/specification, https://www.rfc-editor.org/rfc/rfc3986#section-3.5
You can always read the URL via jQuery URL plugin. It works well.
https://github.com/allmarkedup/jQuery-URL-Parser
There are very few cases when you need to read the URL and extract the GET params. I think that you are doing things wrong and here are my options:
1) if you are having just one page in your app (single app page) you can display results as they type in your input field or after they hit submit
2) if you are redirecting the user to a different page that means you can bootstrap data so that after the page is loaded backbone will just have to render your results and only make other requests if you change your search word
3) you can have a javascript variable which is initialized on page load directly from the server where working with GET params is probably easier