I'm trying to post data from an input and a button group in a component using Ember to my REST API using the actions up method, but the code is confusing me a bit and I haven't found a clear example of how to do it.
The site is a tracker for competitive games in Overwatch, so enter the rank after the game and see it in a list. There is one table, and one endpoint with no children in the API. Basically a simple to-do app, but i'm using components to keep everything modular. I also want to add edit and delete, but that is out of scope for this question.
app/templates/components/add-game.hbs
<form class="form-inline">
<div class="form-group">
<label class="control-label">
Rank <small>(After match)</small>
{{input value=rank type="number" min="4" class="form-control"}}
</label>
</div>
<div class="form-group">
<label class="control-label">
Outcome
{{#bs-button-group value=outcome type="radio" onChange=(action (mut outcome)) as |bg|}}
{{#bg.button type="default" value='W'}}Win{{/bg.button}}
{{#bg.button type="default" value='D'}}Draw{{/bg.button}}
{{#bg.button type="default" value='L'}}Loss{{/bg.button}}
{{/bs-button-group}}
</label>
</div>
<div class="spacer"></div>
<div class="form-group">
<button {{action 'saveGame'}} type="submit" class="btn btn-default btn-primary">Save</button>
</div>
</form>
app/components/add-game.js
import Ember from 'ember';
export default Ember.Component.extend({
actions: {
saveGame() {
const outcome = this.get('model.outcome');
const rank = this.get('model.rank');
console.log(outcome);
console.log(rank);
}
}
});
app/application.hb
{{nav-bar}}
<div class="container-fluid">
<div class="row">
<div class="col-md-offset-2 col-sm-8 col-md-8 main">
{{add-game}}
<br>
{{game-table model=model.games}}
</div>
</div>
</div>
{{outlet}}
I feel like I have most of it there, im just missing a few things with the Data Down, Actions Up approach that Ember uses, but haven't found a clear example to work off that is similar to my code. As you can probably tell I've got the code sending the data to the console, but im not sure of the best way to send it up to the route to then be sent to the server. I think I need to use the model, but the specific code
I am using ember-bootstrap for the styling and custom button group component.
The whole project is on Github
You can get an overview of DDAU architecture of Ember here. When you want to send the action up to the parent to handle, you have to notify the component of the action where you want to pass out any event. Here in your case, if you want to handle the action saveGame in the parent (application), then you have to pass the action to the component add-game while invoking the component as below:
**Application.hbs**
{{game-table model=model.games saveGameInParent=(action 'saveGameInParent')}}
where saveGameInParent is the action present in the application controller. In the component, you need to call out this action explicitly to pass out the control from the component to parent.
**component/add-game.js**
import Ember from 'ember';
export default Ember.Component.extend({
actions: {
saveGame() {
// do you really mean to access these props from model??
const outcome = this.get('model.outcome');
const rank = this.get('model.rank');
this.saveGameInParent(outcome, rank);
}
}
});
And finally, in you application controller, there should be action named, saveGameInParent to handle the bubbled up action from the component.
**controllers/application.js**
actions: {
saveGameInParent(outcome, rank) {
// post your result to the server using any network library.
}
}
PS: It looks like you have mentioned rank and outcome as your direct component property in the component's template file. but in the saveGame action, you tried to access those from model, which you cannot do.
Related
I want to use custom templates for the tree nodes as shown here on their website
https://angular2-tree.readme.io/docs/templates
But I also need the checkbox tri-state functionality as demonstrated here
https://angular2-tree.readme.io/docs/tri-state-checkboxes
In this custom treeNodeFullTemplate example they have a checkbox as part of the template but it doesn't have the tri-state relationship between the parents and children. Is there a way to have a custom checkbox and keep all the correct event listeners etc.? I can't seem to find any documentation on the checkboxes API if there is one.
<tree-root id="tree" [focused]="true" [nodes]="nodes">
<ng-template #treeNodeFullTemplate let-node let-index="index" let-templates="templates">
<div class="tree-node">
<input type="checkbox" [checked]="node.isActive" (change)="node.toggleActivated(true)" />
<tree-node-expander [node]="node"></tree-node-expander>
<div
class="node-content-wrapper"
[class.node-content-wrapper-active]="node.isActive"
[class.node-content-wrapper-focused]="node.isFocused"
(click)="node.toggleActivated(true)">
<span [class]="node.data.className + 'Index'">{{ index }}</span>
<span [class]="node.data.className" [class.title]="true">{{ node.data.title }}</span>
</div>
<tree-node-children [node]="node" [templates]="templates"></tree-node-children>
</div>
</ng-template>
</tree-root>
I can see that the (change) method on the checkbox is not right but do I need to write my own one to get the parent and children and determine state on click? It seems strange that I can't just tap into an existing API.
I have a form in Angular 2 with a simple validation using Validators.
The html template
<form role="form" #myForm="ngForm" (ngSubmit)="submit()" novalidate [ngFormModel]="form">
<div class="form-group list-element">
<label for="name">name*</label>
<input type="text" name="name" class="form-control" ngControl="name"
#name="ngForm" placeholder="Enter name" [(ngModel)]=user.name >
</div>
</form>
The ControlGroup for the validation
ngOnInit() {
this.form = new ControlGroup({
name: new Control('', Validators.compose([
Validators.required,
Validators.pattern("(([a-zA-Z ]|[0-9])+)*"),
Validators.minLength(5),
Validators.maxLength(80)
]))
});
}
When I type fast (random) characters in the input field (e.g #1KZBZKBjkndedjk###kjbzdzdékj!) the application crashes. This does not happen always so I have not really noticed a pattern.
This is the place where the crash happens, so I think the crash has something to do with the pattern.
That's a known issue https://github.com/angular/angular/issues/7822 and will probably be fixed when this pull request lands https://github.com/angular/angular/pull/7421
First of all this is not related to AngularJS.
This happens because your pattern is wrong I don't know what pattern you need but for example if you need to validate email then use this pattern
& Just Check for your pattern nothing else.
your code....
Validators.pattern("^[_a-z0-9]+(.[_a-z0-9]+)#[a-z0-9-]+(.[a-z0-9-]+)(.[a-z]{2,4})$"),
your code ends...
That it!
Assuming that i have the following data in my params
params:[input:[1, 2, 3]]
And i have the following form in my Grails app
<div class="block1">
<label class="control-label">
<g:message code="input.label" default="Input"/>
</label>
<div class="controls">
<g:textField id="input1" name="input" value="${input}" readonly="${actionName != 'show' ? false : true}"/>
</div>
</div>
<div class="block2">
<label class="control-label">
<g:message code="input.label" default="Input"/>
</label>
<div class="controls">
<g:textField id="input2" name="input" value="${input}" readonly="${actionName != 'show' ? false : true}"/>
</div>
</div>
<div class="block3">
<label class="control-label">
<g:message code="input.label" default="Input"/>
</label>
<div class="controls">
<g:textField id="input3" name="input" value="${input}" readonly="${actionName != 'show' ? false : true}"/>
</div>
</div>
The form design above is correct, because in my form design, there will be several inputs of the same name (but each will be saved to the database under different primary keys) and it can be increases and decreases according to user selection.
Few questions using the above
How do i make it so that the value for input1 is params.input[0], input2 is params.input[1] and input3 is params.input[2] in the view? I can pass the model from controller without problem, but i couldn't distribute the value properly to each input on the form.
Is there any way to change the value ${input} dynamically? As in if i want to change the value to ${input[0]} or ${input[1]}
Can i automatically set the amount of block appended into the form using the g:each tag? Say like if from controller i want to set the rendering block amount to 3, so can i use the g:each tag to render the block 3 times in the form?
Thanks
The links are examples of how to use ajax/jquery to get values from a remote call and replace html element (divId) within a page - this divId could be the entire
<input type="text" name="input" value="newvalue"/>
upon triggering some form of call as above to get the new value.. in regards to
g:textField
yes it works like all other grails tags in the end they are transformed back to the correct HTML terminology...
The actual variable value is dynamic if you defined
<input name="existingvariable" value="${something}" ...
where something was a parameter from the given controller - and then you updated the call so
://YOURHOST:8080/yourapp/controller?existingvariable=newvalue
and refreshed or clicked this link which is what ajax would be doing for you doing a new call to either another controller to generate new values or same and passing new value to it and then grabbing data and pushing it back onto the divId ... (all in the background)
Groovy loading into divs
Grails - Select menu not rendering
I want my selects dropdowns to auto populate with Ajax in Grails website
The above are all related to using ajax to populate / update existing form elements
If you wish to update a live form with a new live value (non existant in DB) take a look at modaldynamix plugin. //github.com/vahidhedayati/modaldynamix
When form is nested, the first inner form can not be referred in the controller scope.
I have created a minimal test to reproduce this issue at Plunker
angular version: 1.2.16
Browser: Chrome, Safari
What's the problem? is there any way to remedy?
I recommend a book called Mastering Web Application Development with AngularJs
There's a section called nesting forms and there it says that you have to nest the forms with ng-include. like so:
<script type="text/ng-template" id="password-form">
<ng-form name="passwordForm">
<div ng-show="user.password != user.password2">
Passwords do not match
</div>
<label>Password</label>
<input ng-model="user.password" type="password" required>
Creating Advanced Forms
[ 158 ]
<label>Confirm Password</label>
<input ng-model="user.password2" type="password" required>
</ng-form>
</script>
<form name="form1" novalidate>
<legend>User Form</legend>
<label>Name</label>
<input ng-model="user.name" required>
<ng-include src="'password-form'"></ng-include>
</form>
We define our subform in a partial template. In this case it is inline in a script block
but it could be in a separate file also. Next we have our container form, form1,which
includes the subform by using the ngInclude directive.
The subform has its own validity state and related CSS classes. Also, notice
that because the subform
I have found a workaround for this issue, just replace outer form tag with ng-form tag then the first inner form is added to the scope. see this plunker
I have this situation in which I show 1 form in two steps. So to proceed to the second part of the form you have to click on a button. But before moving on I would like to perform form validation (all required fields need to be filled in). But because this is a normal button, the whole submit magic is not triggered and the validation does not happen. So the question I'm interested in is how can I trigger form validation in my controller ? It would even be better to trigger validation for specific fields. Just to give an idea, the form looks like
<form name="form" submit="save()">
<section id="step1">
<label for="username" required>Username</label>
<input type="text" name="username" ng-model="user.username" required />
.....
<button ng-click="proceed()">Proceed</button>
</section>
<section id="step2">
<label ...></label>
<input...>
....
<button type="submit">Save</button>
</section>
</form>
Also, I don't want to opt for disabling the button until all required fields are valid.
Take a look at the ng-form directive. It allows nesting forms (actually not HTML <form>s, but Angular NgFormControllers). So you can split your one form, used for posting to the server, into two logical forms, used for independent validation:
<form submit="save()">
<div ng-form="form1">
...controls...
<button ng-click="proceed()"
ng-disabled="form1.$invalid">Proceed</button>
</div>
<div ng-form="form2">
...controls...
<button type="submit"
ng-disabled="form2.$invalid || form1.$invalid">Submit</button>
</div>
</form>
You can access the $valid property from your controller. Something like this could work.
$scope.proceed = function(){
if($scope.form.username.$valid){
//username is valid we may proceed to the next step
}
};
<button ng-click="proceed()">Proceed</button>
Replace To :
<button ng-click="proceed()" ng-disabled="form.$invalid">Proceed</button>
Button will not visible button until all required fields are valid.
DEMO