Angular ng-switch with ng-show not respecting DOM order - angularjs

I'm coming to Angular from a jQuery / Backbone background so I'm new to Angular. Anyway, so I'm trying to show/hide divs based on select box values. Basic stuff I know.
The problem is that with the code block below even though <div ng-show="designer"> is the last element in the DOM it shows up before both of the switch-when statements. Moving it around makes no difference.
<select ng-model="designer">
<option value="designerYes">Yes</option>
<option value="designerNo">No</option>
</select>
<div ng-switch on="designer">
<div ng-switch-when="designerYes"...>
<div ng-switch-when="designerNo"...>
<div ng-show="designer">
</div>
I suspect the problem is related to when the events switch and show events are fired but I'm not sure how the best way to troubleshoot or fix the problem. Any ideas on a solution?
UPDATE: The solution (for my case at least) was to not mix ng-switch and ng-show. The first answer right. Because the switch statements aren't in the DOM they are appended after the already available ng-show div.
Here's the answer...
<select ng-model="designer">
<option value="designerYes">Yes</option>
<option value="designerNo">No</option>
</select>
<div ng-show="designer == 'designerYes'"...>
<div ng-show="designer == 'designerNo'"...>
<div ng-show="designer">
This will always show the 3rd DIV when a selection is made and conditionally one of the others based on value.

Initially designer will be undefined until you make a selection. So the 1st two won't be rendered I guess. Can you initialize it with one of the values and see if that helps?

Related

AngularJS <select> dropdown is empty depending on placement in template

I'm experiencing some peculiar behavior based on the <select> tag. It seems that the dropdown is empty depending on where I place it in the template. For example, this works:
<div ng-if="admin.editingRole">
<select ng-options="role.name for role in $data.roles" ng-model="admin.editRole"></select>
</div>
But if I include the exact same element in another place:
<div>
<label for="role">Role</label>
<select ng-options="role.name for role in $data.roles" ng-model="admin.editRole"></select>
</div>
The dropdown is empty. I can't for the life of me figure why this would happen.
It seems that the original developer was using getData() method to populate a $data object from what I can understand, whose scope is only the table contained within the view. Seems to be deprecated and poorly documented so it was a little confusing, and that's why I couldn't access the $data variable anywhere in the view.

Angular translate inner content

How to make angular translate work with inner content? By default it removes everything inside the element containing the translate directive.
When using the directive translate to translate stuff, the framework removes everything inside the HTML element.
In most cases this is not a problem since, you will want your translation to take all your content.
However in some cases it's annoying, for example with labels, see the following plnkr. The following translation will remove the select element.
<label translate> STATE
<select ng-model="selectedItem" ng-options="item.name for item in items track by item.id"></select>
</label>
<label translate="STATE">
<select ng-model="selectedItem" ng-options="item.name for item in items track by item.id"></select>
</label>
https://plnkr.co/edit/wcMuDVMhxH3wbSUTUwtY?p=preview
I am aware that I could use the attribute for or label in this case to solve the problem in this particular case, but I'm after a general solution.
The for attribute you mentioned about is a good way to go, in fact it is the correct and semantic way of doing it:
<label for="state" translate>STATE</label>
<select
ng-model="selectedItem"
ng-options="item.name for item in items track by item.id"
id="state"></select>
i think you can try this instead
<label> {{'STATE'|translate}} </label>
<select ng-model="selectedItem" ng-options="item.name |translate for item in items track by item.id"></select>
works like charm on my side
p.s : i cant edit your plunker due to my internet connection issue. but I tested what I ust done like above and it works well on my side as long as the translations json is matched with your options
edit : sorry. i forgot to put close tag of label :'(

AngularJS form vaidate with radio buttons and ng-repeat

I'm trying to validate a form that is dynamically generated with JSON data, that is rendered to the page using ng-repeat. The data is questions with corresponding answers. The issue I'm running in to is that with a dynamic ng-model on each group, like so:
<div class="well question-well" ng-repeat="question in Posttest1Questions">
<p><strong>{{question.question}}</strong></p>
<ul>
<li ng-repeat="answers in question.answers">
<input type="radio" name="Q{{question.id}}" ng-model="question_[question.id]" id="{{question.id}}" value="{{answers.id}}" required data-key="{{answers.isCorrect}}">{{answers.answer}}
</li>
</ul>
</div>
Even when all the questions are answered, the form never turns valid. In turn, if I remove the ng-model attr, the form is always valid, even if no radio buttons has been selected.
Example Plunkr: http://plnkr.co/edit/DvcJ8byS0yF7iLp37Ets?p=preview
You can use ng-required to set a condition on the input's required status. In this case, if the model used with ng-model is null, then required. Otherwise, not required.
This way, once you've selected one of the answers (the model has a value), all of the answers for this question will not be marked as required.
<input type="radio" name="Q{{question.id}}" ng-model="question[question.id]" id="{{question.id}}" value="{{answers.id}}" ng-required="question[question.id] == null" data-key="{{answers.isCorrect}}" />
See it working here.
The underscore in
ng-model="question_[question.id]" seems wrong to me.
Please try ng-model="question[question.id]" then you can simply say required
updated your plnkr: http://plnkr.co/edit/gCZHFqd07880Os8FcxhG?p=preview

How to make simple form more React-like? (DOM node goes missing)

I am converting a little HTML/JS form I did years ago, as a React.js learning exercise, and I have run into a stumbling block which I'd like to understand the reason for.
Basically, as it originally was, I had a select, where you could choose which form you wanted to display. The onchange handler for the select displayed the chosen form and hid the others. So my first step in doing a React makeover of this, which has worked fine, is to make the forms into React components. I am left with this as my HTML:
<body>
<div id="main">
<select id="calculations" onChange="handleSelect();">
<option value="" selected="selected">SELECT CALCULATION FORM</option>
<option value="1">Enter pace and distance to get a total time</option>
<option value="2">Enter distance and target time to get the required pace</option>
<option value="3">Enter pace and time to get the distance run</option>
<option value="4">Convert mph to mins/mile</option>
<option value="5">Convert mins/mile to mph</option>
</select>
<div id="calcForm"/>
</div>
</body>
This is the JS:
window.handleSelect=function(){
var selected=$("#calculations").val();
if(selected!=""){
React.render(React.createElement(CalcForm, {selected: selected, distances: distances}),document.getElementById('calcForm'));
} else {
$("#calcForm").html("");//clear it
}
};
I have been frustrated, though, in my attempts to finish the job off my making the main select into a React component. I tried creating a SelectCalc component and using it like this:
<body>
<div id="main">
<div id="selectCalc"/>
<div id="calcForm"/>
</div>
</body>
In my app.js I had this:
React.render(React.createElement(SelectCalc,null), document.getElementById('selectCalc'));
I made the handleSelect a function of the SelectCalc class, so that when an option was selected, it called this:
React.render(React.createElement(CalcForm, {selected: selected, distances: distances}),document.getElementById('calcForm'));
Here is where the problem came in, though. When done this way, when I select an option I get the error:
Error: Invariant Violation: _registerComponent(...): Target container is not a DOM element.
The target container in question is the 'calcForm' div, as identified in document.getElementById('calcForm'). For reasons which baffle me, this is null (I checked in the console). And yet it is clearly there in the HTML, and it was successfully targeted by my more primitive select change handler, prior to the React makeover.
So what is the issue? What am I misunderstanding here? Given that this is such a very simple example of React.js at work, how should I be doing it?
Fiddle of non-working version at https://jsfiddle.net/JohnMoore/7rp3n1oy/2/, I hope - first ever use of Fiddle (!), so I hope it shows the issue. Try running it and selecting one of the options and see the error in the console. There is also a preceding error, I notice, on JSFiddle: "SyntaxError: expected expression, got '<'". I have to say this doesn't make much sense to me, as I would have thought what was expected in the return from the render was, precisely, some HTML beginning with <. I don't know whether this is related or whether it's an artefact of the Fiddle environment.
i solved it by removing the divs. They will be create dynamically in the react component.
Here is the fiddle.
EDIT: The old one did not work because <div id="selectCalc" /> is "invalid" html. it will be replaced with <div id="selectCalc"> instead of <div id="selectCalc"></div>. And because there is a missing end-tag, the browser ignores everthing after the <div ... />. -> <div id="calcForm" /> won't appear in the DOM.
Here is a version with the corrected html tags, but you should prefer the other version.
Take a look at this for more information about in/valid html tags.

Loading angular view dynamically based on selection from dropdown

The following is something that I'd like to accomplish with Angular but I'm not sure if it's even possible.
My form would be comprised of 3 views/templates each with it's own controller. Two views are fixed, the third view needs to by dynamically loaded based on a value selected from a dropdown in one of the fixed views. The view and controller name would be derived based on the selected value. If possible I'd like to dynamically load the javascript for the controller of the selected view as well.
I heard some rumblings about this possibly in Angular 2.0 but I'm not exactly sure how to approach it.
Any thoughts? I'm not stuck with Angular so if another framework would work better in this case please let me know.
Unless you are talking about ng-route and $routeProvider, you can have it with ng-include.
By setting ng-include as dynamic, your html will be downloaded and replace the section.
NOTE: however, ng-include does not allow to have script tag in it.
You need to go around using your own directive.
This is the example of using ng-include,
http://plnkr.co/edit/nlGVNfSpJOjIfIXxpEKc?p=preview
<body ng-app ng-init="dynamic='1.html'">
<select ng-model="dynamic">
<option value="1.html">dynamic 1</option>
<option value="2.html">dynamic 2</option>
<option value="3.html">dynamic 3</option>
</select>
dynamic: {{dynamic}}
<div>Fixed 1</div>
<div>Fixed 2</div>
<div ng-include="dynamic"></div>
</body>

Resources