I have some data in my MySQL with HTML code.
Example:
<b>William Shakespeare</b> was an English poet.
I need to insert this text into a Vue.js Component.
My code is:
mounted() {
axios
.get(MY API)
.then(response => (this.author = response.data))
.catch(error => error("error"));
}
And then:
<p class="card-text">
{{author.description}}
</p>
The problem is the tags into the description aren't interpreted and it shows the HTML tags.
Use v-html directive on your parapraph:
<p class="card-text" v-html="author.description" />
But BE VERY CAREFUL about the possibility of XSS attack if author.description is going to contain user provided data.
Related
Given example from the docs
<button hx-post="/clicked"
hx-trigger="click"
hx-target="#parent-div"
hx-swap="outerHTML">
Click Me!
</button>
I want to change <scheme>://<netloc>/clicked to<scheme>://<netloc>/api/v1/clicked, so prepend /api/v1 into the base URL so all requests use this version. How to do that?
The only solution I can think of is to just alter the event path.
<script>
document.body.addEventListener('htmx:configRequest', (event) => {
event.detail.path = `/api/v1/${event.detail.path}`
})
</script>
I'm trying to create a simple app where a picture gets uploaded, and that picture is drawn on html canvas so that i can do some simple pixel manipulation.
Right now I have the GET method for root render an EJS template with a fileReader and a canvas.
With code attached at the bottom of the EJS file through script tags, I draw the uploaded image onto the canvas so I can read each pixel's rgb values.
I then tried to send those rgb values to the POST route in the app (through fetch), but it's not working as expected.
app.post("/", (req, res)=>{
console.log("inside post");
console.log(req.body);
res.render("test", {result: req.body});
console.log("after res.render");
});
All three of the console logs print correctly in the terminal, including the request body, but the test template is not being rendered. It just stays on the same "index" view the app launches with.
Can someone give me some insight as to why this is happening? I also included console logs inside the script tags in the ejs template, and these are only displayed in the browser, not in the terminal I launch the express app with. How can I render the view inside the post method?
First
If you use AJAX like Fetch API or XHR, browser will not render the test page.
Because it's asynchronous, and you could see Ajax in MDN web docs.
You need to use form post with following code.
<form action="/" method="post">
<button type="submit">go to another page</button>
</form>
But, if you use form post, your page which might be "index.ejs" will be replaced with "test.ejs".
In other words,
Browser uses the response from the forms POST request to load the new page.
But browser pass AJAX request's response to a callback and trigger callback in js.
Browser handle these two type request (Form Post and AJAX POST) with different ways.
In common, both are sending data to server.
So, in your case, res.render is triggered successfully.
Let me show you an example. Here is my server code.
const express = require('express')
const app = express()
app.set("view engine", "ejs")
app.get("/", (req, res, next) => {
res.render("test")
})
app.post("/test", (req, res, next) => {
res.render("other-test")
})
app.listen(3000)
<!-- test.ejs -->
<h1>this is test pages.</h1>
<!-- other-test.ejs -->
<h1>this is other test pages.</h1>
When I type url http://localhost:300, browser show me this.
And I open console in chrome and type following code.
fetch("/test", {
method: 'POST', // or 'PUT'
body: JSON.stringify({}), // data can be `string` or {object}!
}).then(res => {console.log("trigger response")})
Then go the network tab in chrome, you will see the request.
Here, this request trigger the express method.
But, what is the response?
Well, it's a html. That means res.render("other-test") is triggered correctly.
And you will find the console output show "trigger response" which callback is triggered in my fetch.
And, page still stay in "test.ejs".
Next, I add following code in my test.ejs
<form action="/test" method="post">
<button type="submit">Go to other page</button>
</form>
Page will be like this.
After you click, you will find out the browser show you "other-test" content.
That's a difference between form post and ajax post.
Second
You put script tag into ejs template.
Express will use ejs engine to render your ejs template become to html page.
After it become to html page, it means all script is running in browser not your nodejs terminal.
I'm currently developing a universal app using Nuxt.js, the data on most of the pages is retrieved from an API using a fetch hook as well as vuex store. I started noticing errors on page reload/refresh and sometimes when I visit a page from the navbar. The page error is:
TypeError: Cannot read property 'data' of undefined
where data is an object retrieved from an API. I have searched around the internet for this and found it has something to do with data not being loaded or page rendering whilst the data is not fully retrieved. i have found a work around by using a v-if on my template to check if the data is set then display the contents. my question is if there is a way to achieve this, i have tried using the async/await keywords but it doesn't help and i feel like the v-if method is not the best way to handle it.
edit: solved by using $fetchState.pending when using fetch()
If in your template you display right away the data you retrieve from the API, then indeed using the v-if is the right way to do.
If you are using the new fetch() hook, then in your template you can use $fetchState.pending to check if the loading has finished, for example:
<div v-if="$fetchState.pending">
<p> Content is loading... </p>
</div>
<div v-else>
<p> Content has loaded! {{data}}</p>
</div>
<script>
export default{
data(){
return{
data: null
}
}
async fetch(){
this.data = await getSomeAPI
}
}
</script>
First the page was rendered by the server, then on client/ browser side, the Javascript script re-render the whole page!
I don't think this is how it's supposed to be since it's very bad user experience.
One thing I noticed is that the data-reactid attribute of my root element as rendered by server is some hash like .2t5ll4229s and all the children has that as prefix e.g. .2t5ll4229s.0 (the first child). Whereas, on the browser side, the data-reactid is .0 for the root element and .0.0 for the first child.
If data-reactid is really the culprit here, is there a way to set it a value of choice like eric123 for both client side and server side.
If data-reactid is not the culprit here, how do I go about making server and client side rendering of React seamless i.e. only certain elements should be re-rendered by the client side, not everything!?
My index-server-local.html template:
...
<body>
<div id="content" class="container-fluid wrapper no-padding-left no-padding-right">
{{{reactHtml}}}
</div>
<script src="bundle.js"></script>
</body>
...
My server.js:
server.get('*', function (req, res) {
console.log('request url', req.url);
log.debug('routes are', JSON.stringify(routes));
res.header("Access-Control-Allow-Origin", "*");
match({routes, location: req.url}, (error, redirectLocation, renderProps) => {
if (renderProps) {
let htmlStr = React.renderToString(<RoutingContext {...renderProps} />);
res.render('index-server-local', { reactHtml: htmlStr });
}
}
My browser.js:
React.render(<Router history={history} routes={routeConfig} />, document.getElementById('content'));
I'm using react-router 1.0.0 and React 0.13.3.
We need serialize data(or state) in server side, and send it to client side to deserialize, otherwise, the data in client side is different with the moment server render it. it will reload for sure.
One exception: pure static page, in this case React recommend us use renderToStaticMarkup
Similar to renderToString, except this doesn't create extra DOM attributes such as data-react-id, that React uses internally. This is useful if you want to use React as a simple static page generator, as stripping away the extra attributes can save lots of bytes.
So, how we serialize - deserialize?
Here is a simple version:
in your index-server-local.html template:
<script src="bundle.js"></script>
to:
<script dangerouslySetInnerHTML={{{{__html: 'window.__data=' + JSON.stringify({key: 'value'})}}}} />
<script src="bundle.js"></script>
And in client side, we can use __datadata now. how to map the data to your component it's based on your choice.
I recommend Reudx for this:
createStore(browserHistory, initialState)
And then
<Provider store={store}>
{ component }
</Provider>
I'm in the process of creating a application using Hot Towel, which supports multiple language (eg. english, french)
I have the referred the following links
Translating Views
Durandal localization example
And my question is how can i render views of application based on user language. If user selects english, the complete application should display contents in english. How to achieve this
I have tried something like in the second link.
define({
'root': {
welcome: 'Welcome!',
flickr: 'Flickr'
},
'fr-fr': true,
'es-es': true,
});
Is this i have to create seperate views for languages or i have to create seperate App folder for contents
Suggest me some best practices.
I don't recommend using separate views or separate folders if your project is a big one.
You can just create a file of the labels and if you use lib like knockout just data-bind these labels once (text: xxxx). In addition you can use i18n to manage labels.
With selected language just load the specific language file to your viewmodel.
EDIT1:
I'd never encountered a complete sample nor tutorial. So how I do is to :
use tools like i18n to get the key-paired dictionary file for labels in html and in some javascript code like messages.
then manually I indexed these labels by augmenting knockout viewmodels for views and variables for modules.
This is my last option in waiting for better solution. Hope this can help!
you can do some thing like this . YOu can change the APP folder if you are need do lot of locale changes you can use the following method
#{
string strAcceptLanguage;
strAcceptLanguage = System.Configuration.ConfigurationManager.AppSettings["Locale"].ToString();
if (strAcceptLanguage == "en-us")
{
#Scripts.Render("~/Scripts/vendor.js")
<script type="text/javascript" src="~/Scripts/require.js" data-main="en-US/main"></script>
}
else if (strAcceptLanguage == "es-es")
{
#Scripts.Render("~/Scripts/vendor.js")
<script type="text/javascript" src="~/Scripts/require.js" data-main="en-UK/main"></script>
}
else if (strAcceptLanguage == "fr-fr")
{
#Scripts.Render("~/Scripts/vendor.js")
<script type="text/javascript" src="~/Scripts/require.js" data-main="AUZ/main"></script>
}
}
in the Index.cshtml you can use the above code and for the you need to have value in Webconfig file
<add key="Locale" value="en-us" />
and in the SPA page each time when the user try to change the locale by pressing button or any kind of option you have to trigger a event to call a AJAX post to assess a REST api to update the Given Locale Value in the webconfig file
changeLocale: function (val) {
var name = JSON.stringify({
locale: val
});
$.ajax({
cache: false,
url: "http://localhost:49589/api/Locale",
type: "POST",
dataType: "json",
data: name,
contentType: "application/json; charset=utf-8",
processData: false,
success: function (json) {
alert(json);
location.reload();
},
error: function (json) {
alert("error" + JSON.stringify(json));
}
});
you have to write the above code in the shell.js and the shell.html has the following code
<div class="btn-group" data-toggle="buttons-radio">
<button type="button" class="btn btn-primary" data-bind="click: changeLocale.bind($data, 'en-us')">English</button>
<button type="button" class="btn btn-primary" data-bind="click: changeLocale.bind($data, 'es-es')">French</button>
<button type="button" class="btn btn-primary" data-bind="click: changeLocale.bind($data, 'fr-fr')">Japanese</button>
</div>
And the rest api like this
[HttpPost]
public string ChangeLocale(Locale l)
{
ConfigurationManager.AppSettings["Locale"] = l.locale;
return "success";
}
hope this will help