Evaluating an expression which contains an expression - angularjs

I am a newbie to Angular js and I just started doing a project in Angular JS.
Let me give you a brief idea about my application. I have a json data which contains data of some nodes, which form a hierarchy. I am using to display this data. So It will take one node at a time and display based on the data in it. I need to display a select field based on the data.
Everything worked fine until I need to display error messages, if the user doesn't select a value in the field. It should be displayed on that particular node. For this I should identify each node( as this is a template). I mapped the id in the data as the name of the select tag, made the tag as required and written a span which displays an error message.
This span will be displayed based on the condition
$error.required
.
The code snippet is as follows.
<form class='css-form form-search' name="myForm" novalidate>
......
<script type="text/ng-template" id="mynodetemplate">
........
<select name="{{node.id}}" ng-model="node.attributeId" ng-options="attribute.id as attribute.name for attribute in attributes" ng-show ="node.showData" required>
<option value="">Select an Attribute</option>
</select>
<span ng-show=”myForm.node.id.$error.required" style="text-align:center; color:red">Please select</span>
'''''''
</script>
..........
<div ui-tree id="tree-root">
<ol ui-tree-nodes ng-model="nodes">
<li ng-repeat="node in nodes” ui-tree-node ng-include="mynodetemplate”></li>
</ol>
</div>
..........
But I am not able to give the correct expression here-
ng-show=”myForm.node.id.$error.required"
I have tried so many ways to evaluate the correct expression, but its not working.
Any help appreciated.
Thanks in advance.

Just as in JavaScript, if you want the name of an object attribute to be node.id, you can't just write
object.node.id
because that references the attribute id of the attribute nodeof the object. So you're forced to use
object['node.id']
So your expression should be
ng-show="myForm['node.id'].$error.required"
But I agree with charlieftl in the comments. You're making your own life difficult by choosing a name containing a dot. Just rename it nodeId, and you can use
ng-show="myForm.nodeId.$error.required"
EDIT:
The name is now in fact a dynamic name. So, in JavaScript you would use
object[node.id]
In the expression, since the scope is implicit, you would use
ng-show="myForm[node.id].$error.required"

I have used the solution posted here
What I have done is that , I will just check whether value exists in the modal or not, or its length.
A sample snippet from the answer is as follows
<input ng-model="somefield">
<span ng-show="!somefield.length">Please enter something!</span>
<span ng-show="somefield.length">Good boy!</span>
Thanks #Supr for the answer.
I dont know why the form validation is not working though :(

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.

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.

What magic does ngModel use that modifying the scope directly does not?

Learning angularjs at the moment, and I am confused as to how I can accomplish a task because I don't fully understand what ngModel is doing.
If I have a directive with two scope variables:
// An array of all my objects
$scope.allMyObjects
// The currently selected object from the array
$scope.selectedObject
and in the html
<span>{{ selectedObject.name }}</span>
<select id="select"
ng-model="selectedObject"
ng-options="object in allMyObjects">
</select>
This all works perfectly, when I select an object from the select, it updates the selectedObject on the scope and so the name of the currently selected object is displayed.
However, I don't want a select box, instead I want a list of all my objects with an editable name field, with a select button that I can use to select the specified object, so I came up with the following:
<div ng-repeat="object in allMyObjects">
<input class="object-name"
ng-model="object.name">
<a ng-click="loadObject(object)">Load</a>
</div>
and the loadObject() function on the scope:
function loadObject(object) {
$scope.selectedObject = object;
}
However, this doesn't work. I had assumed this was basically what ngModel was doing behind the scenes but am obviously confused. Is anyone able to shed some light or offer a better solution to what I wish to achieve?
Please see here :http://jsbin.com/jocane/1/edit?html,js,output
use ng-model="object.name" instead "sc.name"
<div ng-repeat="object in allMyObjects">
<input class="object-name"
ng-model="object.name">
<a ng-click="loadObject(object)">Load</a>
</div>
After an hour of debugging it came down to an issue with the scope being isolated by the ng-repeat, the problem didn't show up in any of the simplified jsfiddle examples because they used pure JS and it was the way I was accessing the scope via typescript that caused the issue.
Thanks for the answers that helped me narrow it down to my difficulty understanding typescript and not my difficulty understanding directives.

selecting an element with no id and name from the typeahead list using css selector

I have to select an element from the auto-complete list.The item has no id and no name.
The following are the details of the inspected element:
<div class="abc-suggestion">
<p class="" style="white-space: normal;">
XYZ
<span class="pull-right"/>
The css selector
.abc-suggestion takes me to
<div class="abc-suggestion">
and
.tt-suggestion>p to
<p class="" style="white-space: normal;">
How can I select the element from the auto-complete list 'XYZ'
(I required to select an element for automating the application using selenium webdriver)
I had a similar problem in Selenium if I understand your question but I don't want to guess. Can you please show the exact html markup for the <div class="abc-suggestion"> and be clear in what you're trying to select within it?
Here's my understanding of your question:
You want to select just the text "XYZ" and you say it has NO id and NO name, but yet, I see "XYZ" wrapped in a P tag. Furthermore, where does the P tag closes?
Please be clear, I think I know what your problem is, it's a simple fix if you show the whole html snippet FOR the <div class="abc-suggestion"> and where that div closes; again just the html code for that div only and what you're tying to select within it should be enough for me or someone else to help you.
EDIT:
Try this:
List<WebElement> paragraphList=null;
paragraphList=driver.findElements(By.cssSelector("span.tt-suggestions p"));
String abcText=paragraphList.get(0).getText();
String xyzText=paragraphList.get(1).getText();

angularjs multilingual text field with ngmodel

I'm trying to implement a multilingual text input field with a little dropdown button to the left for selecting the language. For instance, when the dropdown menu shows 'de' the text field should be bound to model.multilingualData['de'].someField and so on.
My first approach was to set ngModel to model.multilingualData[selectedLanguage].someField. But when the user selects a different language without filling in the field correctly, no error is set on the form, because the model now points to a different object.
My next idea was to create an entire element directive without ngModel, but then I wouldn't be able to do other validations like ngMaxLength.
I couldn't find anything helpful on the web either. Any idea on how to implement this properly?
EDIT
Here's a little fiddle that illustrates the problem: http://jsfiddle.net/FZ2kg/
Not only that the form appears valid when you switch languages, the previous field value is also deleted, because the model is set to null when the field becomes invalid.
would be nice if you use this awesome external directive for multilanguage!
https://angular-translate.github.io/
I hope it helps
If you need to have form validation for all language variations and you're loading all languages at once in your model, can't you just create an input per language in the form and hide all but the currently selected language?
Here's a fiddle: http://jsfiddle.net/jvl70/w3rstmwd/5/
<form name="myForm">
<div ng-repeat="(lang, value) in model.multilingualData"
ng-show="lang==stuff.currentLanguage">
<ng-form name="innerForm">
<div ng-class="{ 'has-error': innerForm.anything.$invalid }">
<input type="text" name="anything" ng-model="value.someField" ng-maxlength="6"/>
</div>
</ng-form>
</div>
</form>
(At first I tried to use dynamic names for each input but found that the individual field $invalid wasn't available for dynamically named inputs. See this post to get around it: Dynamic validation and name in a form with AngularJS.
As an alternative to ng-form, you could use dynamic names for each input and try one of the custom directives on the link.)
I guess if there were many possible languages, this approach might get slower but it's ok for a few languages.

Resources