It's one of the first time that I use express.js and Handlebars.
I need to autocomplete this field: <input type="text" id="myInput" autocomplete="on" placeholder="Search here...">. When everyone digit to this text, I need to make a POST and after a GET without refreshing the content in the page. The problem is, when I do the GET, Handlebars refresh all page. This is the command that I use:
res.render('home',{ items:typeOfCategory});
and this is the structure of the hbs:
{{#if items}}
<ul>
{{#each items}}
<li>{{this.title}}</li>
{{/each}}
</ul>
{{/if}}
My question is: how to avoid the refreshing of the all page?
Thanks
I had read something like that in another question. Based on this tutorial: I found the answer to all my problems.
this tutorial explain how to use a PJAX library that manages both the client and server side.
Thanks to 3 rows of code you can obtain a speed navigation without reload the page.
Install client side library from jQuery-pjax page
into your html page that send the request add: <a href='/yourLink' data-pjax='main'>YourLink</a>
where main is the div that will content yout change. In my case is:
<div id="main" class="main">
{{{body}}}
</div>
In your.js file add $('a[data-pjax]').pjax(); This command 'simply call the pjax extension on every element that contains the data attribute ‘data-pjax’'
Install inside express the depency with the command: npm install --save express-pjax
Set your server:
var app = express();
var pjax = require('express-pjax');
...
app.use(pjax())
Replace the normal rendering:
res.render('index', {title: "Index"});
with
res.renderPjax('index', {title: "Index"});
UPDATE
Alternatively you can obtain the same result. Consider that the structure of the project is as follows:
views
|-> partials
| |-> addtest.hbs
|
|-> index.hbs
For example, image that in your index.hbs you have a sidebar with different items, described in this way:
<li>
<a href="#testDB" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
<img src="../img/database-data.svg" class="svg icon">Test</a>
<ul class="collapse list-unstyled select-specific" id="testDB">
<li value="addTest" class=" ">
Add Test
</li>
....
....
</ul>
</li>
Inside the partials directory you have a simply form.
Now for manage the form you have to do two operations:
Server side: For switching from one partial to another without refresh the page, you specify:
router.get('/addtest', function (req, res) {
res.status(200);
res.header("Content-Type", "text/html");
res.render('partials/addtest', {title: "Add Test"});
});
Client side: In your client side file, you add make a simple get request:
$('#add-new-test').click(function (event) {
$.get('/addtest').then(function (data) {
$('#main').html(data);
});
});
In this way, when you make a get request with the same address (i.e in this case /addtest) the client add a part of code inside your view without refresh all.
NOTE: Keep in mind that, if you needed a some file.js in your partial, for load the file, use this:
<script>
var url = "/scripts/script.js";
$.getScript(url);
</script>
This is used for avoid: “Synchronous XMLHttpRequest on the main thread is deprecated…” because the call is asynchronous. For more info..
The problem here is that you're making the browser request a new resource each time. This is triggering your templating and serving up a brand new page every time.
You'll want to make an express endpoint which returns JSON, and then send up a request to that endpoint using something like AJAX (found in jQuery) or a similar library. This way you can make a call up to your web server, express can return you some data in a JSON format (res.json({}) and your frontend can then interpret that response and decide how to display it on the DOM.
This sort of partial updating is where you start to need frontend JS along side programatic endpoints that return JSON. This is often where some of these big frontend frameworks like Vuejs and Angular thrive, but if you're new to this sort of thing I'd recommend using jQuery to make a HTTP call to your server and return the JSON down to the frontend.
Related
I have the following <a> tag that links to another URL:
<a class="button1 mainButton title" href='/link1'>Sign up</a>
In my Express backend, I am delivering the corresponding HTML file:
router.get("/link1", (req, res) => {
res.sendFile(path.join(__dirname, "../link1.html"));
});
There is an additional functionality that I would like to achieve. I have two types of users, and the identity of the user can only be determined at the frontend. Users who have identity1 should see link1.html, and users with identity2 should see link2.html. I am wondering if there is a possibility to send a JSON object along with the href request. For example, something like <a class="button1 mainButton title" href='/link1' hrefObj = {identity: "identity1"}>Sign up</a> (just made the previous line up). With the sent object, I can send the appropriate HTML file from the backend based on the identity received. I did some research and was not able to find a solution that I was looking for.
I have several a link in 'a' HTML. I expect the page to open in a new window when I click each link and these new windows are using the 'b' HTML. I would like to use 'b' HTML renders different content via different URL, such as /get_node or /get_vue etc. But 'b' HTML has only one URL.
If I pass get parameters to that URL like http://localhost:8000/xxxx.html?show=something,how to make AngularJs can receive this parameters?
For instance, here is 'a' HTML code.
<ul class='list-wrapper'>
<li>Javascript</li>
<li>Node.js</li>
<li>Angular</li>
<li>Vue</li>
<li>CSS/SASS</li>
<li>NPM</li>
<li>Gulp</li>
<li class='getback'><i class="fas fa-times"></i></li>
</ul>
Here is 'b' HTML code, http://XXXXXXXXXXXX.html.
URL get by angularjs via $http.get.
var app = angular.module('app',[]);
app.controller('index',($scope,$http)=>{
$http.get('/get_js',then((res)=>{
$scope.js = res.data;
},()=>{
alert('database error');
})
})
Could anyone tell me how can I do that? Can I put several URLs in $http.get to solve it?
Thank you very much!!
PS: I am using an express server to host the content.
I 'm starting jquery migrating an application to angular, but it has made me a bit complex. I need to know if someone could help me as routing and load controllers, when login any user. There are two types of users
Students
Teachers
Each has a different menu , which in turn has different html pages. Depending on the role the user to enter then load the specific menu.
Using the jQuery load event , and changed the content which changes within a div . I would like to know how to perform this process with angular .
index.html
<html>
<head> Files ... </head>
<body>
<div id="container"></div>
</body>
</html>
student-menu.html
<div>
<div>option-1</div>
<div>option-2</div>
<div>option-3</div>
<div>option-N</div>
</div>
students-pages
option-1.html
option-2.html
option-3.html
option-N.html
teacher-menu.html
<div>
<div>option-1</div>
<div>option-2</div>
<div>option-3</div>
<div>option-N</div>
</div>
teachers-pages
option-1.html
option-2.html
option-3.html
option-N.html
Appreciate a clear explanation.
Please consider reading about including ui-router in your amazing application and learn about templateProviderusage.
As soon as you done with above things all you need is:
Create Service that will have getCurrentUserStatus() that should acquire from loaded data about user his status in your system
Depending on status configure your child views: { 'menu': { ... } } with
//somewhere above
const TEMP = {
user: 'path/to/file.tpl.html',
admin: 'path/to/admin.tpl.html'
}
//somewhere in view configuretion
...,
templateProvider (AuthService) {
return TEMP[AuthService.getCurrentUserStatus()];
},
...
Create all another pages with totally same approach of choosing needed template.
P.S. This allows you to expand list of variable templates unless your imagination will empty :D
P.P.S. Noobs way - lot of ng-include with ng-if on every view that will be changed depending on viewer.
I'm trying to build a site with Laravel to do geolocation. I'm new to Laravel, so first wrote the code in PHP to call two external scripts, one from Google's geoloc API and another from my local server to tell the page what to do:
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=true"></script>
<script src="geoloc.js"></script>
Then, in the body, I put a div for the map and a button to stop querying Google's server:
<body onload="geoloc()">
<p id = 'mapdiv'></p>
<button onclick="stopWatch()">
Stop
</button>
</body>
Everything works fine.
Then I tried to port it over to Laravel. Since this is a front end thing, I wanted to put it in the views, and thought I'd just attach it to the welcome.blade.php view for testing, since I know that one comes up ok. I created a js subfolder in the laravel/public folder, and put the script there. I then used an HTML helper in the header to call up the scripts:
{{ HTML::script('https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=true'); }}
{{ HTML::script('\public\js\geoloc.js'); }}
I appended the PHP in the body:
<p onload="geoloc()" id = 'mapdiv'></p>
<button onclick="stopWatch()">
Stop
</button>
and get nothing. Debugging shows a GET 500 hphp invoke.
Thoughts?
The handlebars documentation shows that one inserts a template in a page by adding a "script" node:
<script id="myTemplate" type="text/x-handlebars-template">
<div>
<h3>cars</h3>
<fieldset>
{{#each model}}
<label class="labels">
{{answer}}
</label>
<br>
{{/each}}
</fieldset>
</div>
</script>
Then doing:
var source = $(#myTemplate).html();
template = Handlebars.compile(source);
and then applying a context to generate the output html.
But instead of inserting the script in the page, I wanted to just get everything from the script tags from my web server. But when I do try to compile the source from my web server, the browser console complains about an unexpected "<" .
What am I doing wrong ?
Sure it is possible.
In this code:
var source = $(#myTemplate).html();
template = Handlebars.compile(source);
Just replace the first line with an ajax call that retrieves the HTML via an Ajax call and then compile the results of fetching the HTML. So, instead of getting the HTML from a script tag, you're getting it from an ajax call just like you would fetch any other data from a web server with an ajax call.
If you're trying that and getting an error, then you will have to be a lot more specific about exactly what code you're using, what error you're getting and what result you're getting back from the ajax call for us to know where you've gone wrong with that. But, if you implement it properly, it's perfectly reasonable to do it that way. You will not want the <script> tags in the HTML you get via the Ajax call, just the raw HTML snippet that represents the template.