I'm working on a larger project and need to create a separate UX for mobile users on some pages. Using a responsive layout with CSS won't cut it, and dynamic component rendering with v-if results in a horrifying template.
This answer is the closest that I have come to, but I want to avoid manually defining routes as there are a ton of pages.
I am currently using a middleware to redirect based on a user agent check:
export default function(context) {
if (context.isMobile) {
if (context.route.fullPath.indexOf('/m') !== 0) {
return context.redirect('/m' + context.route.fullPath)
}
}
if (context.isDesktop) {
if (context.route.fullPath.indexOf('/m') === 0) {
return context.redirect(context.route.fullPath.substring(2))
}
}
}
but I don't have a way of telling whether there is a mobile version or not, so if there isn't, the error page will be displayed.
I also tried working with this answer but using nuxt-device-detect instead of breakpoints, but since the router is configured before getting in the browser, the check function will return the fallback option, so it didn't work well for me. Also since I'll be using SSR I'm avoiding things like document.documentElement.clientWidth.
I guess in short, my question is: what is the best practice for serving separate pages to mobile users?
Related
We are getting some calls to the Selective Cart endpoint, even though this feature is disabled. The problem happens when we access the cart page and the user is logged in.
Trying to figure this out, we have found a piece of code that can explain what might be causing this issue. It's in the SelectiveCartService (https://github.com/SAP/spartacus/blob/develop/projects/core/src/cart/facade/selective-cart.service.ts):
combineLatest([
this.userService.get(),
this.baseSiteService.getActive(),
]).subscribe(([user, activeBaseSite]) => {
if (user && user.customerId && activeBaseSite) {
this.customerId = user.customerId;
this.cartId$.next(`selectivecart${activeBaseSite}${this.customerId}`);
} else if (user && !user.customerId) {
this.cartId$.next(undefined);
}
});
We don't know if we have overridden something that we shouldn't or if this is indeed an issue that must be addressed. Can anyone help?
The selectiveCart.enabled flag is only responsible for handling the “Save for later” button. However, there is one more component that uses SelectiveCartService to call the API and is rendered regardless of the flag value - CMS-driven SaveForLaterComponent. To completely disable the “Save for later” functionality, remove this component from the Sample Data.
I'm learning Nuxt.js and I'm puzzled by how difficult it seems to be to simply redirect a user to another page from a method that is triggered via a click.
Here is the set up: I'm using Nuxt Auth to authenticate users, once authenticated I want them to be forwarded away from the signup page to another route. I already have middleware set up that redirect logged-in users, but it is only triggered when I refresh the page, not when I first log them in.
I have a method like this:
async login(event) {
event.preventDefault()
try {
await this.$auth.loginWith('local', this.loginData)
// this is where my redirect logic should go
} catch(error) { ... }
}
So far I've tried using this.$nuxt.refresh() which doesn't do anything at all and I've also tried this.$router.push('/route') which seems to hang the page completely. Ideally, I would prefer the refresh approach so that I don't have to specify the landing page for logged in users in multiple places, but I also need to know how to use redirections inside methods, I would have thought it should be the most simple operation imaginable and yet it seems to be difficult to find.
Any tips would be highly appreciated!
UPDATE:
I've found a solution, although it's not an ideal one. I've added an if-statement into beforeCreate that checks this.$auth.loggedIn and if it's true, then it calls this.$auth.redirect('home') when "home" is defined in nuxt.config.js under auth redirect. The reason this solution is not ideal is that it relies on the auth module (as opposed to being a general redirect mechanism).
There's a way in Nuxt to reload the page like so:
this.$router.go(0)
also you can find more information here
if this.$router is not working, try this
this.$nuxt.$options.router.push(url);
I have a website that generates a list of items using some javascript and I am trying to scrape it inside my flutter app using beautiful soap package for dart. The thing is that I am unable to scrape the dynamic data generated by the java script. I want to implement a solution that allows me to grab the source code of the website after it fully loads inside the app. A hidden webview inside the app would be perfect but what is blocking me is that how to get the data after the webview loads. This is my main concern. Code examples would be appreciated. Also better practices are welcomed.
What I have came to realize is that scraping dynamic websites that contain some javascript or a website that you want to click in it using a certain script to scrape it properly is not possible over flutter mobile. What you should do is to move the scraping to the cloud by creating your own api then using this api to return the response to your app. This will make scraping easier since you will not have to update your app for every error you find in your scripts. Also imagine that the website that you target updates itself every week, then you will have to update your app every week and wait for approval from all the stores you are subscribed to. A simple example would be using cloud functions from firebase in combination with javascript by utilizing the puppeteer package. A simple video tutorial is here: Tutorial over youtube
After lots of research I did indeed find a way.
Basically loading a hidden webview and scraping the data off of it, then showing it on screen. Here's how..
Spinning a webview in the UI
The Visibility widget and width/height properties will make sure the webview is impossible to be seen by the user. I suggest showing a loading screen until the data is scraped.
Visibility(
visible: false,
maintainState: true,
child: Container(
height: 1,
width: 1,
child: WebViewPlus(
onWebViewCreated: (controller) async {
log.e("onWebViewCreated");
await model.onWebViewCreated(controller);
},
onPageFinished: (url) async {
log.e("onPageFinished");
await model.onPageFinished(url);
},
javascriptMode: JavascriptMode.unrestricted,
),
),
),
The actual scraping
onWebViewCreated(controller) async {
this.webViewController = controller;
// Load the URL
await controller.loadUrl("<Your Website URL Here>",headers:_apiService.getAuthHeader());
// Get the HTML of the webpage as a JSON object
String docu = await webViewController?.webViewController.evaluateJavascript('document.documentElement.innerHTML') as String;
// Convert from JSON to String
var jsonString = json.decode(docu);
// Parse the String to a HTML DOM to actually access the elements
var dom = parse(jsonString);
// Some logic I needed in my application by scraping
for (var child in dom.getElementById("autodl-log-tbody")!.children) {
feed.add(child.text);
}
}
Pro Tip : If you think the webpage might need a bit more time to load, you can stall the execution of the function by using await Future.delayed(Duration(Seconds:5)); before the line of code where you load the URL in the onWebViewCreated() function.
I trying to upload a file using pug, multer and express.
The pug form looks like this
form(method='POST' enctype="multipart/form-data")
div.form-group
input#uploaddata.form-control(type='file', name='uploaddata' )
br
button.btn.btn-primary(type='submit' name='uploaddata') Upload
The server code looks like this (taken out of context)
.post('/uploaddata', function(req, res, next) {
upload.single('uploaddata',function(err) {
if(err){
throw err;
} else {
res.json({success : "File upload sucessfully.", status : 200});
}
});
})
My issue is that while the file uploads successfully, the success message is not shown on the same page, ie: a new page is loaded showing
{success : "File upload sucessfully.", status : 200}
As an example for other elements (link clicks) the message is displayed via such javascript:
$("#importdata").on('click', function(){
$.get( "/import", function( data ) {
$("#message").show().html(data['success']);
});
});
I tried doing a pure javascript in order to workaround the default form behaviour but no luck.
Your issue has to do with mixing form submissions and AJAX concepts. To be specific, you are submitting a form then returning a value appropriate to an AJAX API. You need to choose one or the other for this to work properly.
If you choose to submit this as a form you can't use res.json, you need to switch to res.render or res.redirect instead to render the page again. You are seeing exactly what you are telling node/express to do with res.json - JSON output. Rendering or redirecting is what you want to do here.
Here is the MDN primer on forms and also a tutorial specific to express.js.
Alternatively, if you choose to handle this with an AJAX API, you need to use jquery, fetch, axios, or similar in the browser to send the request and handle the response. This won't cause the page to reload, but you do need to handle the response somehow and modify the page, otherwise the user will just sit there wondering what has happened.
MDN has a great primer on AJAX that will help you get started there. If you are going down this path also make sure you read up on restful API design.
Neither one is inherently a better strategy, both methods are used in large-scale production applications. However, you do need to choose one or the other and not mix them as you have above.
The goal:
Use vue.js to serve a website with many routes and dynamic content which has open graph and twitter rich cards meta data markup.
The idea:
Requests with user agent containing Twitterbot, facebookexternalhit and so on get redirected to a Server Side Rendering website. All the other users get Client Side Rendering version.
The question:
Is it possible in Nuxt.js to make this conditional rendering? If yes, how? If not, any solutions to the above problem?
Credits to the idea
Nuxt can conditionally render a single page (CSR) or not (SSR) after the client request was received:
module.exports = {
path: '/public',
handler(req, res, next) {
res.spa = req.headers['user-agent'] !== 'Twitterbot'
next()
}
}