how to return computed html in vue2? - dom

I try to return the part of html depending on variable type I want to do like:
<template>
<div>{{getvalue(this.$store.state.output)}}</div>
</template>
<script>
export default {
methods:{
getvalue(output){
if(output.constructor == Array){
re="";
for(i in output){
re+=<p>{{i}}</p>;
}
return re;
}
else if(output.constructor == Object){
re="";
for(i in output){
re+=<p><span>i</span><span>{{output[i]}}</span></p>
}
return re;
}else if(output.constructor == String){
return <p>{{output}}</p>
}
}
},
...
}
</script>
I know in react I can use virtualDOM to do that, how should I do the similar things like above in Vue2.5.11?

#ceejayoz is right. It would be missing the whole point of Vue.
Another mistake is that computed values don't accept parameters. It is supposed to be treated as a value and not a function.
This is a more proper way of doing things in Vue. By using v-if and v-for.
<template>
<div>
<div v-if="getOutputConstructor==Array">
<p v-for="i in this.$store.state.output" :key="i">{{i}}</p>
</div>
<div v-else-if="getOutputConstructor==Object">
...
</div>
<div v-else-if="getOutputConstructor==String">
...
</div>
</div>
</template>
<script>
export default {
computed: {
getOutputConstructor() {
const output = this.$store.state.output;
return output.constructor;
}
}
};
</script>
But.. if you really really want to do it the wrong way, use v-html

Related

JS window.onload doesn't load my function

I've got JS form validation code and have to write HTML to it. Unfortunately, something is wrong. Could you please tell me what I am doing wrong? When I click submit button there is no change.
window.onload = init;
function validateForm() {
var user = document.forms["myForm"]["user"].value;
var password = document.forms["myForm"]["password"].value;
if (user == "") {
document.getElementById("poleUser").innerHTML = "<img src='./unchecked.gif'/> Proszę podać nazwisko";
} else {
document.getElementById("poleUser").innerHTML = "<img src='./checked.gif'/>";
}
if (password.lenght < 6) {
document.getElementById("poleHasla").innerHTML =
"<img src='./unchecked.gif'/> Hasło musi zawierać co najmnej 6 znaków";
} else {
document.getElementById("poleHasla").innerHTML = "<img src='./checked.gif'/>";
}
return false;
}
function init() {
document.getElementsByName('myForm').onsubmit = validateForm;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form name="myForm">
Name: <input type="texts" name="user"><span id="poleUser"></span><br>
Password: <input type="password" name="password"><span id="poleHasla"></span>
<br>
<input type="submit" value="Submit">
</form>
</body>
</html>
You need to properly format the function calls
document.getElementsByName('myForm').onsubmit = validateForm;
should be
document.getElementsByName('myForm').onsubmit = validateForm();
(Notice the parentheses at the end).
However, I'd just like to address how you're doing this. In most cases, assigning the onSubmit property statically makes more sense than doing it dynamically. In this case, there really doesn't seem to be any reason for initializing the property using JS.

Mutliple Modals in same page Vuejs 2

I'm a newbie in Vuejs (i'm learning).
I'm trying to do many modals in same page using Vuejs2
Like many people, i have this console warning :
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated:
I read the official doc. I understand that i'm trying to mutating a props and now with vuejs2 its no longer possible.
I tried by using data and computed methods but still doesn't work.
I know the props are now in one way and i think that i understood i need to $emit some props
Here my code:
app.js
Vue.component('modal', Modal);
Vue.component('modal-add-equipe', ModalContent);
Vue.component('modal-user-team', ModalContentTeamUser);
new Vue({
delimiters: ['${', '}'],
el: '#app',
data: {
showModal: false,
showModalAddEquipe: false,
showModalUserTeam: false
},
methods: {
openModal: function(name) {
console.log(this.$refs[name]);
this.$refs[name].show = true;
//this.showModal = true;
},
closeModal: function(name) {
this.$refs[name].show = false;
//this.showModal = false;
}
}
})
Modal.vue
<template>
<transition name="modal">
<div class="modal-mask" #click="close" v-show="show">
<div class="modal-wrapper">
<div class="modal-container with-border" #click.stop>
<slot></slot>
</div>
</div>
</div>
</transition>
</template>
<script>
export default {
props: ['show', 'onClose'],
methods: {
close: function () {
this.onClose();
}
},
ready: function () {
document.addEventListener("keydown", (e) => {
if (this.show && e.keyCode == 27) {
this.onClose();
}
});
}
}
</script>
ModalContent.vue
<template>
<modal :show.sync="show" :on-close="close">
<div class="modal-header">
<slot name="header">
default header
</slot>
</div>
<div class="modal-body">
<slot name="body">
default body
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
</slot>
</div>
</modal>
</template>
<script>
var Modal = require('./Modal.vue');
export default {
props: ['show'],
methods: {
close: function () {
this.$emit('close', false);
},
},
components:{
'modal': Modal
}
}
</script>
the call in twig :
{% for user in usersTeamed %}
<span #click="openModal('userTeam{{ user.getId() }}')"><strong>Equipes</strong></span>
<modal-user-team ref="userTeam{{ user['id'] }}" :show.sync="showModal" #close="closeModal('userTeam{{ user['id'] }}')">
<h3 slot="header">{{ 'equipe_modal_user_equipe'|trans }}</h3>
<div slot="body">
{{ form_start(formUsersTeamed[user['id']]) }}
{{ form_rest(formUsersTeamed[user['id']]) }}
{{ form_end(formUsersTeamed[user['id']]) }}
</div>
</modal-user-team>
{% endfor %}
My goal it's to open one modal (but many in same page and avoid 1k variables like do the example https://v2.vuejs.org/v2/examples/modal.html ) find by "rel"
This code is working but i have console worning !
If someone can help me please :)
PS: I use also gulp with vueify, babelify and aliasify
PS2 : Sorry for my english

Error submitting form data using knockout and mvc

#model NewDemoApp.Models.DemoViewModel
#{
ViewBag.Title = "Home Page";
}
#*<script src="#Url.Content("~/Scripts/jquery-1.9.1.min.js")" type="text/javascript"></script>*#
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<script src="#Url.Content("~/Scripts/knockout-3.3.0.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script type="text/javascript">
var viewModel;
var compViewModel, userViewModel;
$(document).ready(function () {
$(".wizard-step:visible").hide();
$(".wizard-step:first").show(); // show first step
$("#back-step").hide();
var result = #Html.Raw(Json.Encode(Model));
var viewModel = new DemoViewModel(result.userViewModel);
//viewModel.userViewModel.FirstName = result.userViewModel.FirstName;
//viewModel.userViewModel.LastName = result.userViewModel.LastName;
//viewModel.userViewModel.State = result.userViewModel.State;
//viewModel.userViewModel.City = result.userViewModel.City;
ko.applyBindings(viewModel);
});
var userVM = function(){
FirstName = ko.observable(),
LastName = ko.observable(),
State = ko.observable(),
City = ko.observable()
};
function DemoViewModel(data) {
var self = this;
self.userViewModel = function UserViewModel(data) {
userVM.FirstName = data.FirstName;
userVM.LastName = data.LastName;
userVM.State = data.State;
userVM.City = data.City;
}
self.Next = function () {
var $step = $(".wizard-step:visible"); // get current step
var form = $("#myFrm");
var validator = $("#myFrm").validate(); // obtain validator
var anyError = false;
$step.find("input").each(function () {
if (!validator.element(this)) { // validate every input element inside this step
anyError = true;
}
});
if (anyError)
return false; // exit if any error found
if ($step.next().hasClass("confirm")) { // is it confirmation?
$step.hide().prev(); // hide the current step
$step.next().show(); // show the next step
$("#back-step").show();
$("#next-step").hide();
//$("#myFrm").submit();
// show confirmation asynchronously
//$.post("/wizard/confirm", $("#myFrm").serialize(), function (r) {
// // inject response in confirmation step
// $(".wizard-step.confirm").html(r);
//});
}
else {
if ($step.next().hasClass("wizard-step")) { // is there any next step?
$step.hide().next().fadeIn(); // show it and hide current step
$("#back-step").show(); // recall to show backStep button
$("#next-step").show();
}
}
}
self.Back = function () {
var $step = $(".wizard-step:visible"); // get current step
if ($step.prev().hasClass("wizard-step")) { // is there any previous step?
$step.hide().prev().fadeIn(); // show it and hide current step
// disable backstep button?
if (!$step.prev().prev().hasClass("wizard-step")) {
$("#back-step").hide();
$("#next-step").show();
}
else {
$("#back-step").show();
$("#next-step").show();
}
}
}
self.SubmitForm = function (formElement) {
$.ajax({
url: '#Url.Content("~/Complaint/Save")',
type: "POST",
data: ko.toJS(self),
done: function (result) {
var newDiv = $(document.createElement("div"));
newDiv.html(result);
},
fail: function (err) {
alert(err);
},
always: function (data) {
alert(data);
}
});
}
self.loadData = function () {
$.get({
url: '#Url.Content("~/Complaint/ViewComplaint")',
done: function (data) {
debugger;
alert(data);
self.compViewModel(data);
self.userViewModel(data);
},
fail: function (err) {
debugger;
alert(err);
},
always: function (data) {
debugger;
alert(data);
}
});
}
}
</script>
<form class="form-horizontal" role="form" id="myFrm">
<div class="container">
<div class="row">
<div class="col-md-3">
</div>
<div class="col-md-6">
<div class="wizard-step">
</div>
<div class="wizard-step" >
<h3> Step 2</h3>
#Html.Partial("UserView", Model.userViewModel)
<div class="col-md-3"></div>
<div class="col-md-6">
<input type="submit" id="submitButton" class="btn btn-default btn-success" value="Submit" data-bind="click: SubmitForm" />
</div>
<div class="col-md-3"></div>
</div>
<div class="wizard-step">
<h3> Step 3</h3>
</div>
<div class="wizard-step confirm">
<h3> Final Step 4</h3>
</div>
</div>
<div class="col-md-3"></div>
</div>
<div class="row">
<div class="col-md-3"></div>
<div class="col-md-6">
<input type="button" id="back-step" class="btn btn-default btn-success" value="< Back" data-bind="click: Back" />
<input type="button" id="next-step" class="btn btn-default btn-success" value="Next >" data-bind="click: Next" />
</div>
<div class="col-md-3"></div>
</div>
</div>
</form>
I am able to get the data from controller and bind it using knockout. There is a partial view that loads data from controller. But when submitting the updated data, I do not get the data that was updated, instead getting error that "FirstName" property could not be accessed from null reference. I just need to get pointers where I am going wrong especially the right way to create ViewModels and use them.
When you are submitting the form in self.SubmitForm function you are passing Json object which is converted from Knockout view model.
So make sure you are providing the data-bind attributes in all input tags properly. If you are using Razor syntax then use data_bind in Html attributes of input tags.
Check 2-way binding of KO is working fine. I can't be sure as you have not shared your partial view Razor code.
Refer-
http://knockoutjs.com/documentation/value-binding.html
In Chrome you can see what data you are submitting in Network tab of javascript developer console. The Json data that you are posting and ViewModel data structure you are expecting in controller method should match.
You can also change the parameters to expect FormCollection formCollection and check what data is coming from browser when you are posting.

WinJS Repeater and ms-grid: Add ms-grid-row value with JavaScript

I have a series of divs which are displayed as an -ms-grid. These are outputted using the WinJS.UI.Repeater object.
I need to assign the -ms-grid-row value for the current iteration dynamically.
How would I go about doing this?
Repeater
<div data-win-control="WinJS.UI.Repeater" data-win-options="{template: select('.template')}">
</div>
Repeater Template
<div class="template" data-win-control="WinJS.Binding.Template">
<div class="col1" style="-ms-grid-row:"></div>
<div class="col2" style="-ms-grid-row:"></div>
<div class="col3" style="-ms-grid-row:"></div>
<div class="col4" style="-ms-grid-row:"></div>
</div>
CSS
.grid {
display: -ms-grid;
-ms-grid-columns: (1fr)[4];
-ms-grid-rows: (auto)[1000];
}
.grid .col1 {
-ms-grid-column: 1;
}
.grid .col2 {
-ms-grid-column: 2;
}
.grid .col3 {
-ms-grid-column: 3;
}
.grid .col4 {
-ms-grid-column: 4;
}
Because there could be up to 1000 rows, I need to assign the style inline like this:
Rendered Markup
<div class="col1" style="-ms-grid-row: 1">test</div>
<div class="col2" style="-ms-grid-row: 1">test</div>
<div class="col3" style="-ms-grid-row: 1">test</div>
<div class="col4" style="-ms-grid-row: 1">test</div>
<div class="col1" style="-ms-grid-row: 2">test</div>
<div class="col2" style="-ms-grid-row: 2">test</div>
<div class="col3" style="-ms-grid-row: 2">test</div>
<div class="col4" style="-ms-grid-row: 2">test</div>
But I have no idea how to do this inside the repeater?
Many thanks
Chris
You could try using a converter function like explained here:
http://msdn.microsoft.com/en-us/library/windows/apps/br229809.aspx
for example you can assign a function to the colour of a span and calculate that colour in a function:
<span id="loginName"
data-win-bind="innerText: name; style.color: userType LoginData.userTypeToColor">
</span>
...
WinJS.Binding.processAll(document.getElementById("loginDisplay"), LoginData.login);
WinJS.Namespace.define("LoginData", {
//Data Object
login : { name: "myname", id: "12345678", userType: "admin" },
//Converter function
userTypeToColor: WinJS.Binding.converter(function (type) {
return type == "admin" ? "Green" : "Red";
})
});
I did not test this code with the -ms-grid-row property, but it is worth a try.

adding Form Validation Javascript of jquery?

How can I add inline Validation to make sure a choice of radio input must be selected
<script type="text/javascript">
function choosePage() {
if(document.getElementById('weightloss').form1_option1.checked) {
window.location.replace( "http://google.com/" );
}
if(document.getElementById('weightloss').form1_option2.checked) {
window.location.replace( "http://yahoo.com/" );
}
}
</script>
<form id="weightloss">
<input type="radio" id="form1_option1" name="weight-loss" value="5_day" class="plan">
<label for="form1_option1"> 5 Day - All Inclusive Price</label><br>
<input type="radio" id="form1_option2" name="weight-loss" value="7_day">
<label for="form1_option2"> 7 Day - All Inclusive Price</label><br>
<input type="button" value="Place Order" alt="Submit button" class="orange_btn" onclick="choosePage()">
</form>
you are using document.getElementById('weightloss') but infact there is no any element which has id 'weightloss'.
Try with this
<script type="text/javascript">
function choosePage() {
if(document.getElementById('form1_option1').checked) {
window.location.replace( "http://google.com/" );
}
if(document.getElementById('form1_option2').checked) {
window.location.replace( "http://yahoo.com/" );
}
}
</script>
Hope it will help you.
You just had to make js evaluate the form first.
<script type="text/javascript">
function choosePage() {
if(document.forms["weightloss"]["form1_option1"].checked == true) {
window.location.replace( "http://google.com/" );
}
if(document.forms["weightloss"]["form1_option2"].checked == true) {
window.location.replace( "http://yahoo.com/" );
}
else { alert('Please choose an option'); } // for inline alerts see below.
}
</script>
For inline text alerts try the following:
else { my_message.innerHTML = "Please choose an option" }
Add an element to your page to contain the message:
<p id="my_message"></p> <!-- when the form submits empty your message will appear here.