Use VueJs to save a template - static

My project currently is made with VueJS. Now, we need to process a certain template with the input data, then store the result and use it to send an email (for example).
Can i render a template with the user data and save it? how?
I don't want to use another library for this purpose, unless We can't do with VueJS
I have read about SSR. But i don't want to use a server-side rendering. The idea is only render certain messages. Following a behavior like this:
save: function(){
userNote.user = ...
userNote.message = document.getElementById('message').innerHtml;
saveToServer(userNote);
}
The Message template:
<div id="message"> Dear {{user.name}}, please confirm that {{notes}} before {{date}}</div>
I hope i made me understand.
Thanks in advance.

Assuming your template is stored in a component, you could add an export method :
var templateComponent = Vue.component("template-component", {
template: "<p>Hello {{name}}</p>",
props: ["name"],
methods: {
exportHTML: function() {
return this.$el.outerHTML;
}
}
});
var app = new Vue({
el: '#app',
data: {
name: "David",
html: undefined
},
methods: {
getHTML: function() {
this.html = this.$refs.template.exportHTML();
}
}
});
<script src="https://unpkg.com/vue#2.4.2/dist/vue.min.js"></script>
<div id="app">
<div style="display: none">
<template-component :name="name" ref="template"></template-component>
</div>
<label>Name
<input v-model="name">
</label>
<button #click="getHTML">Get html</button>
<pre>{{ html }}</pre>
</div>
Then you just have to call the exportHTML method on the template component to retrieve the HTML.

Related

How to access variables handled by angularjs, using vuejs?

I have an angularjs project and I'm trying to create a page made in angular, using Vuejs.
I've been reading vuejs's documentation but I can't quite figure out how to handle the variables used with angular inside my .twig file.
For instance, if I have something like this:
<section id="ProjectController">
<div class="list-default list-lg">
<a class="animated fade-in-right" v-for="project in projects" ng-href="{% verbatim %}{{ project.url }}{% endverbatim %}">
<project project-on-delete="onDelete" project-show-delete-action="true" project-allow-delete="project.ownerId == user.id" project-show-progress="true" project-show-status="true"></project>
</a>
</div>
</section>
I know ng-controller= id, ng-repeat = v-for
And I have this basic js:
var ProjectController = new Vue({
ready: function () {
this.fetchUsers();
}
el: '#ProjectController',
data: {
projects: null
},
methods:{
getProjects: function(){
this.projects = JSON.parse('array with cluster, id, name, ownerId, etc');
}
},
mounted: function () {
this.getProjects();
}
})
Now, how can I access those variables (Like project or id) inside the json array?
You can simply do:
var projectCtrl = $("#ProjectController").scope();
EDIT
if the `project' directive has isolate scope, then you'll have to enter its scope by using
var projectDirectiveCtrl = $("#ProjectController project").isolateScope();
or
var $project = angular.element("[id='ProjectController']").scope();
since jqLite doesn't support # selector

Multiple Data Bindings in Angular JS

I am new to Angular and would like to know if something like this is possible:
I'm calling data to each story using JSON. Once the story is clicked I would like it to be sent to Javascript, then passed to a different HTML div, the player div.
Is there a way to do that? Or is that not possible with Angular?
For example:
<body ng-app="app" ng-controller"storyCtrl">
<div id="story-1"
class="play_button"
data-id="{id}"
data-title="{title}"
data-storyurl="{fullUrl}"
data-program="{program}"
data-programurl="{program.fullUrl}"
data-type="audio"
data-src="{soundcloudLink}"
data-item-type="story"
data-pub-date="{addedOn}"
data-excerpt="{excerpt}">
</div>
<div id="story-2"
class="play_button"
data-id="{id}"
data-title="{title}"
data-storyurl="{fullUrl}"
data-program="{program}"
data-programurl="{program.fullUrl}"
data-type="audio"
data-src="{soundcloudLink}"
data-item-type="story"
data-pub-date="{addedOn}"
data-excerpt="{excerpt}">
</div>
<!--Here is where I would like the clicked data passed back to:-->
<div id="player">
{{story.Title}}
{{story.Program}}
</div>
</body>
How would I go about creating the variables so that they display the data from the clicked story? Is it possible using Angular's two way binding? I would like them to display the data-information as follows:
var app = angular.module('app', []);
app.controller('storyCtrl', function($scope) {
var story = [
{
Id: 'data-id',
Title: 'data-title',
Storyurl:'data-storyurl',
Program: 'data-program',
Programurl: 'data-programurl',
Type: 'data-type',
Src: 'data-src',
Pubdate: 'data-pub-date',
Excerpt: 'data-excerpt',
},
];
$scope.story = story;
});

Phantom Js with Node and Angular - ng-repeat not rendering

I have an angular App, using angular-ui-router.
Page I have built looks fine.
I am trying to take a snapshot of the html and create a pdf.
To do this, I am using Phantom.
I can trigger and create a PDF fine, but it doesn't render my ng-repeat section of the HTML.
My HTML:
<div>{{vm.hello}}</div>
<div class="row">
<div class="col-xs-2">Heading</div>
</div>
<div class="row" ng-repeat="record in vm.records">
<div class="col-xs-2">Space</div>
<div class="col-xs-2" ng-bind="record.id"></div>
</div>
My controller triggers on load to populate vm.records.
vm.hello is hardcoded and renders fine.
Nothing in my ng-repeat loads.
My Node js code:
var phantom = require('phantom');
function pdf(req, res) {
console.log('pdf function entered');
var url = "http://myapp.com/page";
phantom.create().then(function(ph) {
ph.createPage().then(function(page) {
page.viewportSize = {
width: 1400,
height: 1024
};
page.property('onLoadFinished', function(status) {
console.log("Load Finished with status " + status);
});
page.open(url).then(function(status) {
page.render('test.pdf', {
format: 'pdf',
quality: '100'
}).then(function() {
console.log("File Created");
page.close();
ph.exit();
});
});
});
});
res.status(200).send();
}
Can anyone shed some light as to why the ng-repeat won't work? I've tried adding delays in and such based on other questions/answers, but just can't seem to get it working.
In your controller you have to call
window.callPhantom();
when the render is completed
Next is you have to call it inside $timeout like this
$timeout(function(){
window.callPhantom();
return;
})
to avoid call it before binding

Blaze dynamic data binding

Following is the angular example for simple input field model binding.
<div ng-app>
<div>
<input type="text" ng-model="yourName" placeholder="Enter a name here">
<h1>Hello {{yourName}}!</h1>
</div>
</div>
How can I replicate the same functionality using meteor-blaze with Jade, i.e. input field change event will update the corresponding helper.
Update
Below is my code in Blaze and Jade:
.form-group
lable
| Click buttons to increase their values:
input#user(type="text")
span
|{{usernameinput}}
Below is javascript code:
Template.unitconversion.helpers({
'nm': function(){ return "100" }
});
Template.unitconversion.events({
'keyup #user': function(evt, tmpl){
var tor = tmpl.find('#user').value;
console.log(tor);
//console.log(evt);
//console.log(tmpl);
Template.unitconversion.helpers({
'usernameinput': function()
{
return tor
}
});
}
});
I was expecting the helper function to update the 'usernameinput' whenever user input is changed but nothing happens. I do get the expected console output whenever input field changes.
Any help would be appreciated to solve it.
Let me answer your question in "spacebars". I think you should be able to translate it to "jade" easily. First make sure you add reactive-dict package:
meteor add reactive-dict
It's little more complicated than you might have expected, but the following code should do the the job pretty well:
<template name="hello">
<h1>Wellcome {{myName}}!</h1>
<p>
Tell your name <input type="text" name="myName" value="{{myName}}"/>
</p>
</template>
and the corresponding javascript:
Template.hello.onCreated(function () {
this.state = new ReactiveDict();
});
Template.hello.helpers({
myName: function () {
return Template.instance().state.get('myName');
},
});
Template.hello.events({
'keyup input[name]': function(e, t) {
t.state.set($(e.target).attr('name'), $(e.target).val());
}
});
The reason this is so "complicated" is because Meteor does not offer a built-in two-way-data binding support. It does not mean it can't be done as the above example shows.
You can read more about two-way-data-binding in meteor cookbook here:
https://github.com/awatson1978/meteor-cookbook/blob/master/cookbook/data-binding.md#two-way-data-binding-1
As per Michel Floyd guidance following is the working code:
Jade Template:
.form-group
lable
| Click buttons to increase their values:
input#user(type="text")
span
| {{usernameinput}}
Javascript:
var usernameinput = new ReactiveVar(0);
Template.unitconversion.helpers({
usernameinput: function(){ return usernameinput.get();
}
});
Template.unitconversion.events({
'keyup #user': function(evt, tmpl){
var tor = tmpl.find('#user').value;
console.log(tor);
usernameinput.set(tor);
}
});

AngularJS ngRepeat Not Updating Display Properly

I have have a page where I am using plupload to upload files and having a weird issue with a ng-repeat not updating properly. Here is the relevant code:
<div ng:app>
<div name="myForm" ng-controller="Ctrl">
<input ng-model="test" type="text" />{{test}}<div id="container" class="controls">
<div id="filelist">
<div ng-repeat="file in filesToUpload">{{file.name}} ({{file.size}}) <b>{{file.percent}}</b></div>
</div>
<br />
<a id="pickfiles" href="#">[Select files]</a>
</div>
</div>
</div>​
function Ctrl($scope) {
$scope.test = '';$scope.filesToUpload = [{id: 1, name: 'test', size: '123kb'}];
$scope.addItem = function(object) {
$scope.filesToUpload.push(object);
}
$scope.uploader = new plupload.Uploader({
runtimes : 'html5,flash,browserplus,gears',
browse_button : 'pickfiles',
container : 'container',
max_file_size : '10mb',
url : 'upload.php',
flash_swf_url : '/plupload/js/plupload.flash.swf'
});
$scope.uploader.init();
$scope.uploader.bind('FilesAdded', function(up, files) {
$scope.filesToUpload = [];
$.each(files, function(i, file) {
$scope.addItem({
id: file.id,
name: file.name,
size: plupload.formatSize(file.size)
});
});
console.log($scope.filesToUpload);
up.refresh(); // Reposition Flash/Silverlight
});
}​
Here is a trimmed down jsfiddle showing the issue happening:
http://jsfiddle.net/9HuUC/
To reproduce this issue do the following:
Click on [select files] and selects a few files (notice how you don't see the files displayed anywhere on the output)
Type any character into the input box (magically the files that you select know appear)
What would cause this type of behavior? I mean I know that the data is properly being set in $scope.filesToUpload because I have the console.log() there and even checked it in Batarang and it loods good there but for some reason something else needs to be updated for the display to be updated.
Interestingly enough, I have another ng-repeat that is working fine on the same page. I am wondering if it has anything to do with where the code is (being inside the FilesAdded event on the uploader).
The issue is due to the fact that the FilesAdded callback is executed outside the scope of AngularJS (it's called by the uploader), therefore the scope updates won't be triggered.
To solve this, just add the $scope.$apply call in the callback, encapsulating your existing code:
$scope.uploader.bind('FilesAdded', function(up, files) {
$scope.$apply( function() {
$scope.filesToUpload = [];
$.each(files, function(i, file) {
$scope.addItem({
id: file.id,
name: file.name,
size: plupload.formatSize(file.size)
});
});
console.log($scope.filesToUpload);
up.refresh(); // Reposition Flash/Silverlight
});
});
With this update, it's working in the fiddle. For reference see the AngularJS official documentation, $apply method of the scope object:
http://docs.angularjs.org/api/ng.$rootScope.Scope

Resources