I read a lot of resources about Blaze allowing reactive rendering for Meteor 0.8, but I can't seem to find a solution for my simple problem below.
I'm trying to validate my form inputs. For the sake of simplicity, lets say that I just want to change my {{message}} when a form is submitted. The approach I have taken in client.js is simply giving a new value to the helper variable. This is the way how I used to work with AngularJS, but there seems to be more than simply changing the variable in Meteor. How would I go about this?
- index.html
<template name="user">
<form>
<input type="text" id="name">
<p>{{message}}</p>
<button class="submit" onclick="return false;">Submit</button>
</form>
</template>
- client.js
Template.user.message = "";
Template.user.events = {
'click .submit' = function(){
Template.user.message = "valid";
}
}
It should work if you use a reactive variable. I'll use a session variable in this example:
Template.user.message = function() {
return Session.get('userMessage');
};
Template.user.events({
submit: function() {
Session.set('userMessage', 'valid');
}
});
Note that events takes an object (your code is assigning the click handler rather than making a value in an event map).
Related
I am trying to make a dynamic form using HTML and CSS. I am adding parts of my code below. I can not figure out why the code is not working.
JavaScript:
<script>
$(document).ready(function(e) {
var labelfiled = '<div><label>Label</label><input type="text" name="label[]"></div>';
var valuefiled = '<div><label>Value</label><input type="text" name="value[]"></div>';
var labdiv = $(".labdiv");
var valdiv = $(".valdiv");
var addbutton = $(".add_more");
$(addbutton).click(function(){
$(labdiv).append(labelfiled);
$(valdiv).append(valuefield);
});
</script>
HTML:
<form>
<div class="col-md-6 labdiv">
<div><label>Label</label>
<input type="text" name="label[]">
</div>
</div>
<div class="col-md-5 valdiv">
<div>
<label>Value</label>
<input type="text" name="value[]">
</div>
</div>
<button class="add_more">Add values</button>
</form>
If someone can help it would be great.
I also would like to know how I can process the data when I submit this into a javascript variable in the from of a array. Like for example if i have 2 inputs for value in the from, I want to store them in a javascript array and then convert it into a JSON.
Form must be in method="POST" and if you get in into php function :
if(!empty($_POST) && isset($_POST){ /*try something with $_POST*/ }
Try this
$(".add_more").click(function() {
var postData = {
field1: $("#id_field1").val(),
field2: $("#id_field2").val()
};
$.ajax({
dataType: "json",
data:JSON.stringify(postData),
url: URL,
method: 'POST'
});
});
A few things that may improve your learning:
jQuery and you code
All jQuery code should be wrapped in this...
$(document).ready(function() {
// jQuery
});
On the var's you have created, you have already initialised them as jQuery elements. Therefore, when you reference them again, you do not need (for example) $(addbutton) as addbutton will do. See amended code below)
<script>
$(document).ready(function(e) {
var labelfiled = '<div><label>Label</label><input type="text" name="label[]"></div>';
var valuefiled = '<div><label>Value</label><input type="text" name="value[]"></div>';
var labdiv = $(".labdiv");
var valdiv = $(".valdiv");
var addbutton = $(".add_more");
addbutton.click(function(){
labdiv.append(labelfiled);
valdiv.append(valuefield);
});
});
</script>
The console
On checking the console...
Say, for example, if you write the JS code console.log(1 + 1) in your page somewhere as you want to see that sum. Due to you writing client side code, when your web page loads (and depending where you have put the console.log()) if you check the developer tools in your chosen browser i.e. Chrome or IE, there is a console section where you can see the result of what you printed (i.e. using that example, it would be 2). This console in the browser will also print out errors that it detects (i.e. $ is not defined - if you are trying to reference jQuery but the library isn't included), it's a good tool for web developers (hence the name ;)) for debugging client side code.
Adding elements to array
Code for getting input values on submit of a form: (jQuery)
var array = [];
$("form").on("submit", function() {
$("input").each(function() {
array.push($(this).val();
});
});
I would suggest that you go and read a book/tutorial on jQuery code as well as the basic concepts of web development :)
Examples:
jQuery
For reference to basics if you get stuck, the link above is more reliable:
- w3schools
I'm trying to create a page that requires buttons/tags similar to following image using html:
I'm not sure what these buttons are called. Ultimately I want to create them dynamically since what buttons need to be created are different from different users.
Any suggestions are greatly appreciated. Thanks.
These things are called Chips. If you are using angular, then you can look at the demo here.
You can implement such functionality using jQuery or core javascript.
You can use this jquery readymade plugin
Demo - http://xoxco.com/projects/code/tagsinput/example.html
GitHub Link : https://github.com/xoxco/jQuery-Tags-Input
A solution to this in Angularjs would be to create a controller for your form that determines whether or not the browser is allowed to display your cancel button. This can be created using the following code:
var app = angular.module('formExample', [])
app.controller('ExampleController', ['$scope', function($scope) {
$scope.canCancel = false;
$scope.updateCancelVal = function(myForm) {
$scope.canCancel = $scope.myForm.$valid;
};
}]);
And then in your html, it would look like:
<div ng-controller="ExampleController">
<form name="myFormName">
Name: <input ng-keyup="updatCancelVal(myFormName)" type="text" ng-model="user.name" /><br>
Email: <input ng-keyup="updatCancelVal(myFormName)" type="email" ng-model="user.email" /><br>
<button ng-show="canCancel" href="myCancelLink.html"> Cancel </button>
</form>
</div>
Ultimately, this makes it so that the Cancel button is only shown when canCancel is true. And on each key input in each of the separate inputs, this value is updated until the form is valid. If you need more aid in implementing this, lmk and more detail will be added!
I am experiencing odd behavior when data linking an object to a form that led me to re-question what exactly is being data bound?
Basically I have a form that creates new Companies as well as updates them. The actual creation/update is done via ajax, which is why I am using the same form for both purposes. In the case when I have to create a company, everything works as I expect. However when I have to update a company, things don't work like how I expect them to. Please have a look at the following code.
Here is my sample Form HTML:
<div id="result"></div>
<script type="text/x-jsrender" id="CompanyFormTemplate">
<form>
<input type="text" data-link="Company.Name" />
</form>
</script>
Here is my Javascript code:
var app = new CompanyFormContext();
function CompanyFormContext() {
this.Company = {
Name: ''
};
this.setCompany = function (company) {
if (company) {
$.observable(this).setProperty('Company', company);
}
};
};
$(function () {
initPage();
...
if (...) {
// we need to update company information
app.setCompany({ Name: 'Company ABC' });
}
});
function initPage() {
var template = $.templates('#CompanyFormTemplate');
template.link("#result", app);
}
Instead of the form input showing 'Company ABC', it is empty. However if I enter anything in it, then the Company.Name value does change! But while I want the input to data bind to Name property of my Company object, I also want it to be aware of any changes made to the (parent) Company object and update it's data binding to it's Name property accordingly.
So my question is how should I change the way I am writing this code so that I can achieve a data bound both on the root object as well as the property?
The issue you were having was because in your scenario, you have paths like Company.Name for which you want to data-link to changes not only of the leaf property but also to changes involving replacing objects higher up in the path (in this case the Company).
For that you need to use the syntax data-link="Company^Path".
See the section Paths: leaf changes or deep changes in this documentation topic:
http://www.jsviews.com/#observe#deep.
See also the examples such as Example: JsViews with plain objects and array in this topic: http://www.jsviews.com/#explore/objectsorvm.
Here is an update of your jsfiddle, using that syntax: https://jsfiddle.net/msd5oov9/2/.
BTW, FWIW, in your fix using {^{for}} you didn't have to use a second template - you could alternatively have written:
<form class="form-horizontal">
{^{for Company}}
...
<input type="text" data-link="Name" />
{{/for}}
</form>
To respond also to your follow-up question in your comment below, you can associate any 'block' tag with a template. Using tmpl=... on the tag means you have decided to separate what would have been the block content into a separate re-usable template. (A 'partial', if you will). The data context for that template will be the same as it would have been within the block.
So specifically, {{include}} {{if}} and {{else}} tags do not move the data context, but {{for}} and {{props}} do. With custom tags you can decide...
So in your case you could use either {^{for Company tmpl=.../}} or {{include tmpl=.../}} but in the second case your other template that you reference would use <input type="text" data-link="Company^Name" /> rather than <input type="text" data-link="Name" />.
Here are some relevant links:
http://www.jsviews.com/#samples/jsr/composition/tmpl
http://www.jsviews.com/#includetag
http://www.jsviews.com/#fortag
I discovered one way to achieve this. It might seem complex at first but it will make sense once you understand it properly.
(PS: I wish there was a sample like this. I might just blog about it.)
HTML Markup:
<script type="text/x-jsrender" id="CompanyFormTemplate">
<form>
{^{for Company tmpl="#CompanyDetailsTemplate" /}
</form>
</script>
<script type="text/x-jsrender" id="CompanyDetailsTemplate">
<input type="text" data-link="Name" />
</script>
Javascript: No changes needed from code above.
Okay so as I said, the solution might look complicated but it turns out all I really had to do was to set up data binding first on the Company object, and then to it's property objects. I wonder if there is a more elegant solution (i.e. one in which all of this can be achieved in a single template) however this solution ensures that data-binding is happening both on the parent object as well as its' properties.
I have posted a JsFiddle for this solution, so if anyone comes across this problem and wants to understand how this solution would work for their particular problem, they will be able to play with a working solution.
I used to use Jquery extensively. Now that I stumbled upon Angularjs, I am trying understand how it works and I have been really excited about the AutoMagic way it works. For example, am able to do the below process of hiding and showing few blocks just by using ng-click, ng-hide & ng-show.
<form id="signup-form" ng-submit="processForm()" ng-hide="showConfirm" >
<input type="text" name="user" ng-model="name">
<button type="submit" id="submit" ng-click="showConfirm = ! showConfirm">Submit</button>
</form>
<div class="col-md-12 confirmation" ng-show="showConfirm">
<h2 >Thanks alot for your feedback.</h1>
</div>
But, I am still wondering how can I do the same from code, say from a controller. In Jquery one way to do would be like:
$( "#submit" ).click(function() {
$(".confirmation").show();
$("#signup-form").hide();
});
And maybe if I want to validate the form I can use .preventDefault(); in Jquery and do something. How does all this work in AngularJs?
Just change the model value in your controller: showConfirm = !showConfirm;
This will update your view automatically using the ng-hide and ng-show directives you already have in place.
Better yet, call a scoped function like:
$scope.toggleConfirm = function() { showConfirm = !showConfirm; }
...and call that in your view using ng-click="toggleConfirm()" to keep your code DRY.
I am trying to obtain form data from the Angular controller without success.
HTML:
<form>
<input type="text" id="entityName" ng-model="ent.Name">
<button class="btn" type="button" onclick="this.blur()" ng-click="$event.preventDefault(); saveData()">Save</button>
</form>`
JS Controller:
$scope.saveData = function() {
console.log($scope.ent.Name);
}
I receive error: Error: $scope.ent is undefined
always give form a name if you want angular validation to work. Shouldn't use onclick in angular app (asking for headaches and creating testing problems) ng-clcik will automatically prevent default so you don't need to add that yourself.
You probably haven't set up an object in scope for ent. If your ng-model values didn't have a dot in them you wouldn't need to register anything in scope for ng-model to work automatically creating a scope property
$scope.ent={};
This will be object that your ng-model properties will bind to. Will need to see more code if this isn't the issue