directive "link" doesn't apply as I want it - javascript

Ok I got a page with some input managed with angular x-editable.
fiddle
The following directive:
treeView.directive('selectWhenEditing',function(){
var linkFunction = function(scope,startingelem,attr)
{
console.log(startingelem[0]);
console.log (startingelem[0].querySelector('.editable'));
angular.element(startingelem[0].querySelector('.editable')).on('click',function(){
//console.log(startingelem[0]);
angular.element(startingelem[0].querySelector('.editable-input').select());
});
};
return{
restrict: 'AEC',
link:linkFunction
};}
);
Is supposed to make that when I click on an editable element, the text is selected.
Here is the code of the page:
<tr ng-repeat="properties in elementToEdit" ng-if="fieldsSettings[$index][1]==1">
<td>
{{ fieldsSettings[$index][0] }}
</td>
<td data-select-when-editing>
<span editable-text="properties.prop" onbeforesave="" ng-if="fieldsSettings[$index][2]== 'text'">
{{ properties.prop || 'empty' }}
</span>
<span editable-select="properties.prop" onbeforesave="" ng-if="fieldsSettings[$index][2]== 'select'" e-ng-options="s.value as s.text for s in fieldsSettings[$index][3]">
{{ selectElement(properties.prop,$index) || 'empty' }}
</span>
</td>
</tr>
and that's the relevant compiled HTML:
<tr class="ng-scope" ng-if="fieldsSettings[$index][1]==1" ng-repeat="properties in elementToEdit">
<td class="ng-binding"> Name </td>
<td data-select-when-editing="">
<span class="ng-scope ng-binding editable editable-click" ng-if="fieldsSettings[$index][2]== 'text'" onbeforesave="" editable-text="properties.prop"> Food </span>
</td>
</tr>
The directive is firing as I wish it (eg: the number of times of expect it).
The first console.log logs me the calling TD element as expected. But the second one is null, as it never finds an element ".editable" inside this TD, so obviously the text is never selected (event "on" isn't applied).
I've done the exact same thing in another page/module and it works well. I'm comparing the codes but cannot find a difference.
You guys see something ?

As it says in the docs, jqLite's find() function is "Limited to lookups by tag name", which means you can't use it to select elements by classes - so you need to use querySelector instead. Note that you also need startingelem[0] instead of just startingelem when using it.
I had to use angular.element to get the jqLite object for on() binding (you can use plainJS there as shown below), so it looks a bit ugly:
angular.element(startingelem[0].querySelector(".editable")).on('click',function(){
startingelem[0].querySelector('.editable-input').select();
});
Here is the fully working version: http://jsfiddle.net/ar7znuz5/
Plain JS version using addEventListener:
startingelem[0].querySelector(".editable").addEventListener('click',function(){
startingelem[0].querySelector('.editable-input').select();
});
And the fully working version: http://jsfiddle.net/ar7znuz5/1/
The last version, with selects and a newer original code: http://jsfiddle.net/ar7znuz5/7/

Related

Protractor - find element with "neighbour"

I'm currently creating a tests with protractor and phantomjs.
What I'm trying to do is pretty simple, here is my html code containing the element I want to click.
<tr class="moo" role="foo">
<td class="bar">
<input class="toto" value="42" type="checkbox"></input>
</td>
<td class="titi">
Test
</td>
</tr>
Here I need to click the checkbox element, quite easy actually with :
element(by.xpath("//input[#type='checkbox']")).click();
But the problem is that there is many checkbox elements and the only difference between them is the "a" line with the text (Test in this example) that changes.
My question is : how can I specify that. I want to click on the checkbox Where the text in "a" line is "Test" ?
Use a CSS selector to find the row and then the cell:
element(by.cssContainingText('tr[role="foo"]', 'Test'))
.element(by.css('input'))
.click();
Or with an XPath to find the cell with a single call:
element(by.xpath('//tr[td/a/text()="Test"]//input'))
.click();

AngularJS: render table columns before content is received

How do I make AngularJS render table columns correctly before the intended content for them is received?
I'm using ng-if to show the content, since I need different elements depending on the value that I get back from an API call, see below. This is the only reason for not using ng-bind, which I assume would be a more legitimate solution.
<td ng-if="someArray.length > 0"><a ng-href="someLink">Yes</a></td>
<td ng-if="someArray.length == 0">No</td>
Using this, due to obvious reasons the particular column is not shown at all while someArray is not initiated. I could check for undefined in the second ng-if, but I would rather have the column be completely empty while waiting for a value.
I am still quite new to AngularJS and I assume that there is a best-practice here.
You can use ng-if in internal dom elements
<td>
<a ng-if="someArray.length > 0" ng-href="someLink">Yes</a>
<p ng-if="someArray.length == 0">NO</p>
</td>
You can move the ng-if into the elements within the td:
<td>
<a ng-if="someArray.length > 0" ng-href="someLink">Yes</a>
<span ng-if="someArray.length == 0">No</span>
</td>

AngularJS ng-click inside ng-repeat

I have a ng-click nested inside a ng-repeat, and I am trying to pass a value from the current item in the loop. If I inspect the html generated using Chrome developer tools it looks correct (&ID=1) but when I put a break point in the function it shows &ID={{d.ID}} as the value that gets passed to the function.
Any help is appreciated.
<tr ng-repeat-start="d in data">
</td>
<td>
{{d.OrganizationName}}
</td>
</tr>
Try it:
<tr ng-repeat-start="d in data">
</td>
<td>
<a href="" ng-click="openDialog(false,'http://portal.sharepoint.com/Lists/Organization/DispForm.aspx?IsDlg=1&ID='
+d.ID)"> {{d.OrganizationName}}</a>
</td>
</tr>
I would recommend passing the Id in as an attribute of the openDialog method and building the url string in the controller.
ng-click="openDialog(false,'http://portal.sharepoint.com/Lists/Organization/DispForm.aspx?IsDlg=1', d.ID)"
then build the string in the controller and perform your location change. Easier to debug and un-clutters the view.
you could also store this string in your controller 'http://portal.sharepoint.com/Lists/Organization/DispForm.aspx?IsDlg=1'
ng-click="openDialog(false, d.ID)"
ngClick directive will evaluate an expression. I guess it's not what you want
Try to change ng-click by simple onclick. It will solve your problem:
Change
{{d.OrganizationName}}
for
{{d.OrganizationName}}
With ng-click. you don't need to use {{}} in order to get the variable value. Like in this sample from Angular Docs
<button ng-click="count = count + 1" ng-init="count=0">
Increment
</button>
<span>
count: {{count}}
</span>

Knockout if binding inside a template does not show now matter what value the observable holds?

I have a simple template with an if binding inside it:
<script type="text/html" id="addPersonTemplate">
<tr>
...
<td class="large-7" data-bind="text: addPersonUsername"><span class="noSpecificChecks" data-bind="if: addPersonUsername() == false">No username added</span></td>
...
</tr>
</script>
Basically, a person has an option to enter a username. When they click 'add' somewhere else in the document, the template is outputted, however, no matter what I try:
I cannot get if: addPersonUsername() == false to evaluate correctly.
If the expression evaluates to true (there is no username) I want to output "No username added". Yet, if I enter no username, the addPersonUsername() variable is undefined (checked via console.log) and yet this text is not outputted.
Is there any particular reason for this? Is the if binding only evaluated at HTML page load, not at template addition? I can't see any indication it is...
Knockout observables are functions so you need to get their value with calling them without any argument (e.g.: addPersonUsername()) when they are used in any expression like inside an if binding:
<span class="noSpecificChecks" data-bind="if: addPersonUsername() == false">
Beside that your HTML is structured incorrectly. When you apply the text binding on the td it replaces the whole content of the td so also your span with the if.
So you need to apply the text something else inside the td like on a span (or use the virtual element syntax if you don't need the span):
<td class="large-7" >
<!-- ko if: addPersonUsername -->
<span data-bind="text: addPersonUsername"></span>
<!-- /ko -->
<span class="noSpecificChecks" data-bind="if: addPersonUsername() == false">No username added
</span>
</td>
Demo JSFiddle.

AngularJS - Directives with Angular UI Bootstrap

I'm using Angular UI - Bootstrap, specifically the Typeahead directive. http://angular-ui.github.io/bootstrap/#/typeahead
I'm attempting to use the 'typeahead-template-url' to create custom html templates for my suggestion boxes. After trying multiple techniques, unsuccessfully, I discovered that by purposely messing up my quotation marks 'solved' the display issues. I would love to understand why this is breaking and get it working properly.
For example: this works
<table class="> <!--see class quote error -->
<tr>
<td>
<div ng-mouseenter="selectActive($index)" ng-click="selectMatch($index)">
<a>ID{{ match.model.id }} - {{ match.model.text }}</a>
</div>
</td>
</tr>
</table>
This DOESN'T WORK
<table class="">
<tr>
<td>
<div ng-mouseenter="selectActive($index)" ng-click="selectMatch($index)">
<a>ID{{ match.model.id }} - {{ match.model.text }}</a>
</div>
</td>
</tr>
</table>
FIDDLE is here: http://jsfiddle.net/nicktest222/JXtaZ/24/
Additionally, when you select an item in the results list, it returns the entire object. How can I get it to return a specific property in the object?
Any help would be greatly appreciated.
Thanks
I think it is the way you add your template (columnTwo.html) in JSFiddle.
Look at my demo (which is based on yours): http://jsbin.com/aMOrOra/1/edit?html,js,output
As for the typeahead property:
<input type="text" ng-model="monkey" typeahead-template-url="columnTwo.html" typeahead="suggestion as suggestion.text for suggestion in sample_data | filter: $viewValue" />
Here it means that the suggestion object is used as the selected value, but I want to display only the suggestion.text property in the box. But monkey will still be set to the selected suggestion object.
Just so you know, your current filter will look for the query on every properties of the suggestion object, not only text.
EDIT: To filter only the text property, use the filter like this:
filter:{'text':$viewValue}

Categories