I am trying to use an external JS library that generates a drawing canvas (atrament.js) within a vue.js app.
I am not sure what is the right way of doing this. Right now I am just doing:
<script type="text/javascript">
var main = new Vue({
el: '#vueapp'
});
</script>
<script type="text/javascript">var atr = atrament("canvas", 500, 500);</script>
And with that the canvas is generated wherever I put the <canvas></canvas> tags.
However, this does not seem a very elegant option, and the atr var is not accessible for the vue app, for example for clearing the canvas. So, which is the right way of doing this?
Since Vue is a component-based UI library, you should try to think in components.
Consider wrapping that canvas in a component and your parent element will talk to it via props and events. Vue has a very clean documentation for that: https://v2.vuejs.org/v2/guide/components.html
You should have atr variable as a vue data variable, like following:
<script type="text/javascript">
var main = new Vue({
el: '#vueapp',
data: {
atr : atrament("canvas", 500, 500)
}
});
</script>
Now atr will be available in the vue app via this.atr and you can do required operations on it.
Related
I have a html element textarea_01 to which I want to add a style when I press my button_01 which has an onClick function on it
myFunction: function(event) {
//some code that does something
};
Since I can't use directives with JSX I was thinking that the following will work:
<textarea id="textareaID" style={{resetWidth}}/>
And add to my function that's used on the onClick my code, so it will look like:
myFunction: function(event) {
var textarea = new Vue({
el: '#textareaID',
data: {
resetWidth: 'width: 10px'
}
})
//some code that does something
};
But it's not working and WebStorm tells me
You are using the runtime-only build of Vue where the template compiler is not available
How do I work around this and accomplish what I want to do, which is add a css property to a html element after I click on another element ?
Note: Webpack and the followin is used in the code github.com/vuejs/babel-plugin-transform-vue-jsx Note that almost all built-in Vue directives are not supported when using JSX, the sole exception being v-show, which can be used with the v-show={value} syntax.
You have to bind the style attribute to Vue, because you can't use moustaches on tag properties:
<textarea id="textareaID" :style="resetWidth" />
Because you are using runtime only Vue version, you should try with another approach.
Remove the moustaches from the textarea:
<textarea id="textareaID" />
Set the styles for the element with javascript on the mounted hook or another lifecycle hook that you want:
myFunction: function(event) {
var textarea = new Vue({
el: '#textareaID',
data: {
resetWidth: 'width: 10px'
},
mounted: function () {
this.$el.setAttribute("style", this.resetWidth);
},
})
//some code that does something
};
I have an HTML page updated with ajax contents.
I'm using Vue.js for some dynamic front-end events.
Dynamically added elements don't interact with the Vue.js instance, even if I try to forceUpdate.
How could I do that?
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.0/vue.js"></script>
<div id="app">
<button v-on:click="click()">click will console something</button>
</div>
<script>
var app = new Vue({
el: '#app',
methods: {
click: function() {
console.log('clicked')
},
}
});
setTimeout(function() {
$('#app').append('<button v-on:click="click()">click here wont do anything</button>');
app.$forceUpdate();
}, 1000);
</script>
That is not how you add elements in Vue. Your contract with Vue is that it will control the DOM and you will provide it a model that describes how things should appear and work.
Let go of jQuery. If you want a button to conditionally appear, have a variable that controls its appearance, and set that variable to true.
If you really, really have to deal with DOM being added outside of Vue, then you will need to call new Vue on the newly added elements to put them under Vue's control.
I have very small web page with emberjs, where I want to show some item list and openlayers map for them, and another map for selected item.
Something like that:
<script type="text/x-handlebars" id="list">
<div class="list">
<div id="list_map"></div>
</div>
{{outlet}}
</script>
<script type="text/x-handlebars" id="list/item" >
<div class="item">
<div id="item_map"></div>
</div>
</script>
<script>
function showListMap() {
listMap = new ol.Map({target:'list_map'});
}
function showItemMap() {
itemMap = new ol.Map({target:'item_map'});
}
</script>
There is no problem to display map for list:
model: function(params) {
var content = [];
var url = 'http://localhost:8080/app/list';
$.ajax({
url: url,
success: function(surveys) {
content.pushObjects(surveys);
showListMap();
}
});
return content;
}
and I have action in item controller that is executed, when opening selected item, but if I try to create item map there (in controllers action) it fails (afaik because there is no such div at that moment in DOM).
So if I could execute action or my function after div is already add to DOM, it should work.
And question would be, how to execute something after template is added to DOM, or that's completely wrong way to do such stuff (than what would be correct ember way)?
I can't say much with seeing full code. But to execute some code after the DOM is rendered you schedule a function on the the run loops afterRender queue.
Ember.run.scheduleOnce('afterRender', this, function() {
//The div should be available now.
});
But if you really need to touch the DOM I recommend you wrap your map code in a component. A component gets a didInsertElement where you can write your maps initialization code.
var component = Em.Component.extend({
setup: function() {
//Do you map init here.
}.on('didInsertElement')
});
There unfortunately isn't a really good route or controller hook that fires off after a page has already rendered. I believe the reason for this is that the developers of Ember think it is an anti-pattern to directly talk to the DOM.
That being said, I think it sometimes is quite handy for complex UI on otherwise static web pages. If you want to do some sort of jquery or use the DOM API after a route has rendered, you can do the following in your route file (as #Dainius correctly points out)
routeName.js
import Route from '#ember/routing/route';
import jQuery from 'jquery';
export default class myRouteFile extends Route {
manipulateDom = function() {
$("#myDiv").css( "color", "red" );
}
init() {
this._super(...arguments)
Ember.run.scheduleOnce('afterRender', this, this.manipulateDom)
}
}
I am using Lean Modal: http://leanmodal.finelysliced.com.au/ in a Rails app with a React front-end.
When I put the link to the modal in application.html.erb it works fine but when loaded through a React link using the same code, nothing happens.
I have jQuery loaded and checked 10 times if the code is the same. What could cause such an issue?
Here is the link code in React:
<a rel="leanModal" name="login" href="#login">
The template file (html.erb) script:
<script type="text/javascript">
$(function() {
$('a[rel*=leanModal]').leanModal({ top : 200, closeButton: ".modal_close" });
});
And I am loading the modal JS from my application.js file in Rails.
Thanks for any help!
You should wrap things that interact with DOM (e.g. jQuery plugins) in a component.
var LeanModal = React.createClass({
componentDidMount: function(){
$(this.getDOMNode()).leanModal({
top: this.props.top || 200
});
},
render: function(){
return <div>{this.props.children}</div>;
}
});
Note that you also need to provide a componentWillUnmount to handle clean up, and that the plugin can't do things like add/remove elements. Plugins that don't allow cleanup or make destructive changes are incompatible with react.
Sometimes implementing it with just the existing CSS and using react components instead of the jQuery plugin can be very simple and end up with a better result.
Hi im trying to make a simple feed reader using ember.js and feedek. But so far when I try to place the code for the feed, it not working.
Jquery code for feedek (inside the index template in a script tag):
$('#divRss').FeedEk({
FeedUrl: 'http://vikinglogue.com/feed/',
MaxCount: 100
});
Html Code for template:
<script data-template-name="index" type="text/x-handlebars">
<article style="background-color:#fff;" id="divRss"></article>
</script>
When I run this code in the browser, nothing in the template shows up and I'm not getting any errors. I think the issue is caused by not linking feedek in the template but when I tried it, nothing happened. Thanks, any help is appricated.
To use a jQuery plugin in an Ember app, it's usually best to wrap it in a component:
App.FeedEkComponent = Ember.Component.extend({
tagName: 'article',
didInsertElement: function() {
this.$().FeedEk({
FeedUrl: 'http://vikinglogue.com/feed/',
MaxCount: 100
});
}
});
Then in one of your Handlebars templates,
<p>Your feed:</p>
{{feed-ek}}
I would add to Sam's excellent answer as follows:
Make the component reusable by passing in the url as a property
Don't override didInsertElement hook, instead specify that the function should run on 'didInsertElement' event (see here)
http://emberjs.jsbin.com/boguwagisi/1/edit?html,js,output