I am attempting to generate a form like this:
<div class="col-xs-6" for.repeat="field in ${config.formMain}">
<div class="form-group">
<label>${field.label & oneTime}</label>
<select if.one-time="field.controlType == 'select'" class="form-control">
<option value=""><- Select -></option>
</select>
</div>
</div>
where config is a variable in my view-model.
A couple questions:
1) I have tried both for.repeat="field in ${config.formMain}" and for.repeat="field in config.formMain" and neither syntax seems to work. How am I meant to access the array from the object?
2) Is there any support for something like for.repeat.one-time="field in ${config.formMain}" where this would cause Aurelia to only execute the loop compilation once (which is useful in my case because the form is not going to chage) but keep the bindings inside the loop as default bindings (i.e. if I have a for.repeat inside of the outer one, it should update itself if the array it is iterating over changes)?
Thanks in advance.
The correct syntax is: repeat.for="thing of things"
See that is of instead of in, following the ECMAScript 6 style. More information at https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/for...of
You could use "& oneTime" to execute the loop only once. Like this:
repeat.for="thing of things & oneTime"
Related
I have a form which contains a parent element and a child element, in every browser I can retrieve this value but in MS Edge I am unable to get the key from the parent element. Is anyone able to shed light on this issue?
<div v-for="(levelKey, level) in levels">
#{{ level.name }}
<div v-for="(currencyKey, currency) in currencies">
<input type="text" name="levels[#{{ level.id }}][currency.id]" v-model="...">
</div>
</div>
You can write your type attribute as a bound attribute using the :type syntax. See: https://vuejs.org/guide/syntax.html
Then you don't need the moustache braces (#{{ ... }}) when you're already inside an expression. You can just write:
<input :name="levels[level.id][currency.id]" v-model="...">
or even simpler (since you're already looping through levels):
<input :name="level[currency.id]" v-model="...">
EDIT
I created a JSFiddle with some mock data (probably not exactly the same as yours, though) and tried it in MS Edge. It worked fine:
Maybe you forgot to copy a part of the code?
I have the following code:
<input id="id">
<button data-action="bea" ng-click="Create($('#id1')[0].value);" class="btn">Insert ID</button>
<button data-action="bea" ng-click="Create($('#id2')[0].value);" class="btn">Insert ID</button>
In the JS I have:
$scope.Create = function (id){
if (id === undefined) {
$scope.data = "You must specify an id";
} else {
$scope.data = data;
console.log(data);
});
}
};
When the call gets into the Create function the value of the id is undefined.
If I add the following line at the beginging of the Create function everything works ok:
id = $('#id')[0].value;
If I send a constant value it works:
<button data-action="bea" ng-click="Create('SomeID');" class="btn">Insert ID</button>
Why is this happening and how can I do that without putting the line of value into the method?
Thanks
This is just an extension of comments and other answers, You could achieve this in many ways using angular, one simple example could be:-
<!-- Add a controller -->
<div ng-controller="MainCtrl">
<!-- Give a model binding to your text input -->
<input ng-model="userEntry" type="text"/>
<!-- ng-click pass which ever argument you need to pass, provided it is an expression that can be evaluated against the scope or any constants -->
<button data-action="bea" ng-click="Create(userEntry);" class="btn">Insert ID</button>
<!-- Some simple data binding using interpolation -->
{{data}}
<!-- Just for demo on repeater on a list of items on the scope -->
<div ng-repeat="item in items track by $index">{{item}}</div>
</div>
Example Demo
My 2 cents on the lines of what were originally trying to do:-
Use angular bindings instead of accessing DOM directly for getting the data, it really helps you deal with just the data without worrying about how to access or render it in DOM. If you think you need to access DOM for implementing business logic re-think on the design, if you really need to do it, do it in a directive. Angular is very opinionated on the design and when where you do DOM access.
ng-model
ng-binding
controller
all about ngmodel controller
This is not the way you should do in AngularJS. You should really think in Angular if you want to use AngularJS. Refer this post ("Thinking in AngularJS" if I have a jQuery background?)
All DOM manipulation should be done in Directive. Refer this page that I found really clear.
(http://ng-learn.org/2014/01/Dom-Manipulations/)
My guess is that $ is not bound to the jQuery function when the ng-click value is evaluated, because it is not exposed in the Angular scope.
Solutions to adress this:
expose the jQuery function in scope somewhere, e.g $scope.$ = $; in a controller.
make the Create function parameterless as you suggested, with a var id = $('#id')[0].value; at the beginning
my favorite : avoid using jQuery. If you put some data in the #id element, there's probably a more natural and AngularJS-idiomatic way of retrieving it than querying the DOM (e.g an Angular service).
In particular, if the element you're targeting is an <input> element, then use the ngModel directive to link the value to a $scopeproperty that will be accessible in the controller :
<input ng-model="inputData"/>
The JavaScript you are trying to pass as a parameter of the create function is not available in the scope of the Create function.
Try to target the element a different way.
Does that help?
I have an app with many forms. Each field has several HTML elements, so I thought I could extract some directives (one per type of field) to keep my forms tidy.
I've created a sample app to demonstrate the problem, but I'm getting inconsistent behavior. In the sample app, a <link /> element replaces the <input />. In my real app, <input /> just gets removed from the DOM completely. I feel like this should be easy; why doesn't it work?
To answer your stated question, it's because you told it to, with ng-transclude. That replaces the contents of the tag with the original element, which I don't think you wanted; you probably wanted the original contents to be transcluded as the label instead.
This is probably what you're looking for:
<div class="form-group" >
<label for="{{htmlId}}" ng-transclude></label>
<input id="{{htmlId}}" class="form-control" type="text" ng-model="model" />
<span ng-repeat="error in errors">{{error}}</span>
</div>
I've moved the tranclusion into the label. While this works, I would also recommend the style of actually passing a label attribute, rather than transclude it, just for the sake of having a consistent API and simpler code; it's functionally equivalent, though, so don't let me bully you.
Also, you've got a few errors in your .js as well. First, you want to use = in your scope instead of &
scope: {
model: '=',
errors: '='
},
& is used to pass methods, while = is used for objects (this is a simplification). Since your model and errors are objects, you'll want to use = instead.
Finally, in your example, your html template and your directive's template don't have the same name... you've got an extra 's' in your .js, but that's probably just in the plunker and not your real app.
I'm exploring the Meteor-framework. I've a lot of experience with Java EE / JavaServer Faces (JSF), but I'm new to JavaScript-development. I'm trying to create a nicely formatted "horizontal form", as described at http://twitter.github.io/bootstrap/base-css.html#forms. My problem is, that this gives me a lot of repeated HTML for each input field, which is not DRY...
So, I'm trying to create a construct like "composite components" in JSF 2.x. This means I'm looking for a way to call a Meteor-template and substitute some values in it.
My template is like this:
<template name="formField">
<div class="control-group">
<label class="control-label" for="{{this.id}}">{{this.label}}:</label>
<div class="controls">
{{this.formField}}
</div>
</div>
</template>
I was able to get it partially working, by calling it like this:
{{> formField labels.x}}
Where I defined the labels map like this:
Template.myTemplate.labels = {
"x": {id: 'idx', label: 'labelx'},
"y": {id: 'idy', label: 'labely'},
"z": {id: 'idz', label: 'labelz'}
}
The problem is, of course, substituting the <input>-element in the template. I tried all sorts of ways to do this, but there are several problems:
I could add the <input>-element to my formField-template, but then I cannot bind the value of that <input>-element to a property of the JavaScript-object that is being edited in the form.
I could create a function that returns an <input>-element, but then I would end up with markup-code in my JavaScript-sources.
Another problem is that I'm not really satisfied with the Template.myTemplate.labels-map. It seems this is unavoidable, since I was not able to use any literal values. It would be nice if I was able to call the template like this:
{{> formField idx labelx}}
{{> formField idy labely}}
{{> formField idz labelz}}
To conclude, I have basically one question: what's the best way to create some sort of component with Meteor/Handlebars?
Forms are on the roadmap:
https://trello.com/card/easy-forms/508721606e02bb9d570016ae/8
But in particular check out this discussion:
https://github.com/meteor/meteor/issues/1054 (from the above link).
As for creating components in Meteor, there is no the way to do it, but you might want to check out how the accounts packages work, as that's pretty isolated, extensible, and a form:
https://github.com/meteor/meteor/tree/master/packages
I have a character which can contain multiple skills.
Skills are available from an injected service.
What I basically want is this:
<div ng-repeat="skill in character.getSkills()">
<select ng-model="skill" ng-options="select as s.toString() for s in getAllSkills()"></select>
<button ng-click="character.removeSkill(skill)" >Remove Skill</button>
</div>
With this code, the select box doesn't work as I would expect it. Skills are not set in the character, and selections are not kept in the drop down.
Am I missing something?
Thanks in advance,
roemer
After all, I'm referencing the skill in the character.skills array by the $index property in the child scope:
<select ng-model="character.skills[$index]" ng-options="sk as sk.toString() for sk in getAllSkills()"></select>