I'm following this tutorial and any time it references an input element it defines them as so:
{{input type="text action='actionname'... }}
I'm told this is out of date and indeed the docs don't use that format, instead using this format:
<input type="text" {{action 'actionname' ... }}
I'm at the point of the tutorial where I'm saving data to the store. I've amended the tutorial to use angle brackets instead of curly braces like so:
<input type="text" value={{model.name}} class="form-control" placeholder="The name of the Library" />
<input type="text" value={{model.address}} class="form-control" placeholder="The address of the Library" />
<input type="text" value={{model.phone}} class="form-control" placeholder="The phone number of the Library" />
<button type="submit" class="btn btn-default" {{action 'saveLibrary' model}}>Add to library list</button>
My route looks like:
import Route from '#ember/routing/route';
export default Route.extend({
model() {
return this.store.createRecord('library');
},
actions: {
saveLibrary(newLibrary) {
newLibrary.save().then(() => this.transitionTo('libraries'));
},
willTransition() {
this.controller.get('model').rollbackAttributes();
}
}
});
When I call the route action saveLibrary and open the debugger, newLibrary doesn't have any data from the model properties. Whenever I change the handlebars template to use curly braces like the tutorial, it works fine; newLibrary contains name, address & phone.
What is the syntax for using angle brankets and having it propagate to route.js?
The angle bracket component should be <Input> not <input>.
Related
I am currently building my first, very basic react app. There is a button that triggers an API call using onClick. However, react just doesn't seem to be rendering the onclick to the DOM.
Within index.js I have, among other, the following content:
<NumberSelect
label={"Can I get your number?"}
id_input1={"number-input"}
placeholder={42}
onClickEvent={RequestFact}
cta={"Get Fact"}
/>
This is my NumberSelect.js:
import Button from "./Button.js";
import InputNumber from "./InputNumber.js";
import "./NumberSelect.css";
const NumberSelect = (props) => {
return (
<form id="number-select">
<label htmlFor={props.id_input1}>{props.label}</label>
<InputNumber
placeholder={props.placeholder}
id_input1={props.id_input1}
/>
<Button
cta={props.cta}
class={"btn mt-10"}
href={props.href}
onClickEvent={props.onClickEvent}
/>
</form>
);
};
export default NumberSelect;
And this is the entire Button.js
import "./Button.css";
const Button = (props) => {
return (
<a
id={props.id}
className={props.class}
href={props.href}
onClick={props.onClickEvent}
>
{props.cta}
</a>
);
};
export default Button;
What I would expect the HTML to look like is this (note: is defined in a separate Component):
<form id="number-select">
<label for="number-input">Can I get your number?</label
><input
type="text"
inputmode="numeric"
pattern="[0-9]*"
id="number-input"
placeholder="42"
spellcheck="false"
data-ms-editor="true"
/><a class="btn mt-10" onclick="RequestFact()">Get Fact</a>
</form>
But this is what the HTML actually looks like:
<form id="number-select">
<label for="number-input">Can I get your number?</label
><input
type="text"
inputmode="numeric"
pattern="[0-9]*"
id="number-input"
placeholder="42"
spellcheck="false"
data-ms-editor="true"
/><a class="btn mt-10">Get Fact</a>
</form>
Almost everything is the same, only the onclick="RequestFact() is missing.
Can anybody help me out? Do you need any other info?
Thanks for your help!
Edit: I tried to simplify the code a bit and not post everything here. But it seems I took away too much and it became unclear. Sorry for that. Above some additional code.
Info regarding the additional questions:
RequestFact ist located in index.js
Thanks for the tip regarding { for strings - will implement
Is it possible to add a vue input component to a standard html form? I know this is not the ideal way to handle vue forms, but I'm curious about the possibility as a "quick and dirty" way for adding custom elements into pre existing html forms. Here's a hypothetical example:
<form action="/users" accept-charset="UTF-8" method="post">
<input type="email" name="user[email]" />
<input type="password" name="user[password]" />
<my-custom-fancy-vue-component />
<input type="submit"value="Sign up">
</form>
I'm wondering if the browser can read the value exposed by an input element withen the vue component and send that as a param when the user submit the form. Is there any other way to tell the browser how to access the value from a vue component if for example it doesn't use a native input internally, perhaps using a web component as a wrapper or using shadow dom?
Any <input> elements within the form should be included by the browser when the form is submitted. The browser won't care that the <input> is inside a Vue component.
For components that don't already have an <input> (or other suitable form element) you can add a hidden input, <input type="hidden">, to hold the value.
If the component you want to include is a third-party component then you won't be able to add the hidden input directly. However, you could still add it by using a wrapper component. The example below illustrates how you could handle that scenario.
const thirdPartyComponent = {
template: `
<button
#click="onClick"
type="button"
>
Increment {{ value }}
</button>
`,
props: ['value'],
methods: {
onClick () {
this.$emit('input', this.value + 1)
}
}
}
const myCustomFancyVueComponent = {
template: `
<div>
<third-party-component v-model="counter" />
<input type="hidden" :value="counter">
</div>
`,
components: {
thirdPartyComponent
},
data () {
return {
counter: 4
}
}
}
new Vue({
el: 'form',
components: {
myCustomFancyVueComponent
}
})
<script src="https://unpkg.com/vue#2.6.11/dist/vue.js"></script>
<form action="/users" accept-charset="UTF-8" method="post">
<input type="email" name="user[email]">
<input type="password" name="user[password]">
<my-custom-fancy-vue-component></my-custom-fancy-vue-component>
<input type="submit" value="Sign up">
</form>
****EDIT: PROBLEM SOLVED! Neuronet's solution was the answer:
<div ng-repeat="post in $ctrl.posts">
<textarea class="postBox" ng-model="$ctrl.comment.content" name="content" /></textarea>
<input type="submit" id="submit" value="Submit" ng-click="$ctrl.postCommentSubmit(post.id)" />
</div>
Below is my original post:
I've spent the past 3 hours on this problem. I have an array of posts that I have passed from my controller to my template under the name "posts". Each post in posts is an array holding various key-value pairs such as "id" (value being an integer), "content" (value being a string), etc. I want to include a form to send a PostComment post to my api. The PostComment post requires that I send it a foreign key (representing the related post) and a content field. I wish to get the foreign key dynamically from ng-repeat .
My template looks like this:
<div ng-repeat="post in $ctrl.posts">
....
<form ng-submit="$ctrl.postCommentSubmit()">
<input class="hidden" type="text" ng-model="$ctrl.postCommentArray.postForeignKey" value="{{ post.id }}" name="postid" />
<textarea class="postBox" ng-model="$ctrl.postCommentArray.content" name="content" /></textarea>
<input type="submit" id="submit" value="Submit" />
</form>
</div>
The pertinent part of my controller looks like this:
self.postCommentArray = {
content: '',
postForeignKey: '',
};
I am attempting to get the foreign key from post.id (the "post" is from post in $ctrl.posts in ng-repeat). I cannot seem to figure out a way to do this. I have tried both value="{{ post.id }}" and ng-value="{{ post.id }}" but for various reasons neither works. Ng-value only works on radio, but I cannot automatically check the option, and value does not work together with ng-model since they are both competing to set the value.
I'd be much obliged to anyone who could help me.
Why are you using the CommentArray ? just use comment as your model
You can pass a post id in postCommentSubmit
<div ng-repeat="post in $ctrl.posts">
<textarea class="postBox" ng-model="post.comment.content" name="content" /></textarea>
<input type="submit" id="submit" value="Submit" ng-click="$ctrl.postCommentSubmit(post.id)" />
</div>
I would suggest in your controller make your postCommentSubmit function look something like this:
$ctrl.postCommentSubmit = function (post, foreign_id) {
$http.post('/api', {
"post_comments": post["post_comments"],
"user": post["user"],
"timestamp": post["timestamp"],
"updated": post["updated"],
"content": post["content"],
"post_likes": post["post_likes"],
"id": post["id"],
"foreign_id": foreign_id
})
}
And then in your html ng-submit:
<form ng-submit="$ctrl.postCommentSubmit(post, $ctrl.postCommentArray.postForeignKey)">
I need to send route params with the URL when the user clicks on submit button.
Here is my simple form
<form action="#/chat/{{username}}">
<input type="text" placeholder="enter a username..." ng-model="username" required autofocus><br/>
<input type="submit" value="submit">
</form>
But this doesn't work as the 'username' variable doesn't bind and it goes to /chat/%7B%7Busername%7D%7D instead (somebody enlighten me on why this happens)
Currently, the workaround I am following is using a hyperlink instead of a submit button
<div>
<input type="text" class="form-control" placeholder="enter a username..." ng-model="username" required autofocus><br/>
<a href="#/chat/{{username}}" class="btn btn-lg btn-primary btn-block" >Start Chatting</a>
</div>
But the problem with the above approach is that it doesn't work when the user presses ENTER key (as it is not the submit button)
So what is the correct way to achieve this?
Markup:
<form ng-submit="onSubmit()">
<input type="text" placeholder="enter a username..." ng-model="username" required autofocus><br/>
<button type="submit">submit</submit>
</form>
JavaScript Controller:
app.controller('ctrl', function($location) {
$scope.username = '';
$scope.onSubmit = function() {
$location.url('/chat/' + $scope.username);
};
});
Or something like that :)
HTML:
<form ng-submit="onSubmit()">
<input type="text" placeholder="enter a username..." ng-model="username" required autofocus><br/>
<button type="submit">submit</submit>
</form>
Controller:
app.controller('ctrl', function($state) {
$scope.username = 'example name';
$scope.onSubmit = function() {
$state.go('/chat/' + $scope.username);
};
});
Docs:
Angular Ui
$state.go('$scope.username') - will go to the state according to user name
$state.go('^') - will go to a parent state
$state.go('^.sibling') - will go to a sibling state
$state.go('.child.grandchild') - will go to grandchild state
Per another post on stack:
the $location service is on the angular.js framework out of the box and allow you to manage location object (similar in pure javascript). The $state service is part of ui-router module and allow you to manage routes in an advanced mode, throughout a state machine management of views.
If you use ui-router, you should prefer to use $state service to manages states/routes because state abstracts the concept of route and you could change the phisical routes without changing states.
Stack Post
I'm trying to use Angular's built-in form functions, specifically setPristine() to clear the form on user submit. My controller has access to $scope.newForm (my form) with all of its methods, but running $scope.newForm.$setPristine() isn't resetting the form fields.
Here is my HTML:
<div ng-controller="NewFormController">
<h3>New Entry</h3>
<form name="newForm" method="post" novalidate>
<div class="input-group">
<label>Name</label>
<input name="name" type="text" ng-model="place.name"/>
</div>
<div class="input-group">
<label>Description</label>
<textarea name="description" type="text" ng-model="place.description"></textarea>
</div>
<div class="input-group">
<label>Neighborhood</label>
<input name="neighborhood" type="text" ng-model="place.neighborhood"/>
</div>
<div class="input-group">
<label>Address</label>
<input name="location" type="text" ng-model="place.address"/>
</div>
<input type="submit" value="Submit" ng-click="submit(place)"/>
</form>
</div>
And here is the controller where I call setPristine():
app.controller('NewFormController', function($scope, $compile) {
$scope.place = {
name: 'ExamplePlace',
description: 'This is a description!',
neighborhood: 'Manhattan',
address: '112 Street Place'
};
$scope.submit = function(place) {
$scope.newForm.$setPristine();
$scope.newForm.$setUntouched();
};
});
Here is a working codepen that reproduces my problem.
Note: I'm using Angular version 1.4.3.
$setPristine only marks the form as being $pristine, which is useful for validation-driven expressions and CSS (e.g. .ng-dirty)
So, $setPristine does not clear the form's controls. In fact, it wouldn't even know how to do that. Consider, that to "clear" could mean different things to different models. "Clear" could mean "", or undefined, or null, or anything at all that a custom input control that works with ngModel could mean.
So, to properly clear the form is to modify the View Model that drives the form to whatever definition of "clear" it needs. In most cases - yours included - it is just a matter of setting the View Model to a new object:
$scope.submit = function(place) {
$scope.newForm.$setPristine();
$scope.newForm.$setUntouched();
// clear the form
$scope.place = {};
};