I want to scroll down to page. When I clicked anchor , I want to stay on same page but focus on partivular element or page down. How can I achieve this?
Create an element reference in your component like this
#ViewChild('whatever') myElement: ElementRef;
Bind it to the html element like this
<input #whatever />
Then you should be able to call focus to it like this.
function focusWhatever() {
this.myElement.nativeElement.focus();
}
Element References are a powerful tool in Angular for accessing DOM elements directly, particularly for stuff like this. Read more about them here.
Read more about the el.focus() DOM API method here.
Related
I'm setting HTML returned from the API in my Angular component:
<div [innerHTML]="content"></div>
content in this example is something like this:
<table>
<tr>
<td>[audioPlayer:file.mp3]</td>
</tr>
</table>
Now I would like to inject the actual component inside the table cell.
If I make a certain container, I can create the component with createComponent:
audioPlayerComponentRef: ComponentRef<AudioPlayerComponent>;
#ViewChild('placeholder', { read: ViewContainerRef }) container;
const factory: ComponentFactory<AudioPlayerComponent> =
this.componentFactoryResolver.resolveComponentFactory(AudioPlayerComponent);
this.audioPlayerComponentRef = this.container.createComponent(factory);
Then I can inject it into a container in the template:
<div #placeholder></div>
However, going back to my original goal, I can't use such a container, as the component needs to be injected into a specific position into an innerHtml block.
I've been brainstorming all day, but I can't see any way to achieve this.
Generally speaking, this is contrary to the way Angular works. [innerHTML] is not parsed for any Angular functionality. No component selectors or even a ViewContainerRef can be found there. Rather, even remotely suspicious HTML, CSS and JS is removed as a security measure as Angular only trusts its own templates.
So InnerHTML is a no-go. But I was in the same boat myself and have written a library to solve this exact problem. With it, you can freely load dynamic components into strings without compromising security. If you're still stuck on this, you might wanna have a look at it.
I'm starting to learn angularJS better, and I've noticed that AngularJS tries to make strong emphasis on separating the view from the controller and encapsulation. One example of this is people telling me DOM manipulation should go in directives. I kinda got the hang of it now, and how using link functions that inject the current element allow for great behavior functionality, but this doesn't explain a problem I always encounter.
Example:
I have a sidebar I want to open by clicking a button. There is no way to do this in button's directive link function without using a hard-coded javascript/jquery selector to grab the sidebar, something I've seen very frowned upon in angularJS (hard-coding dom selectors) since it breaks separation of concerns. I guess one way of getting around this is making each element I wish to manipulate an attribute directive and on it's link function, saving a reference it's element property into a dom-factory so that whenever a directive needs to access an element other than itself, it can call the dom-factory which returns the element, even if it knows nothing where it came from. But is this the "Angular way"?
I say this because in my current project I'm using hard-coded selectors which are already a pain to mantain because I'm constantly changing my css. There must be a better way to access multiple DOM elements. Any ideas?
There are a number of ways to approach this.
One approach, is to create a create a sidebar directive that responds to "well-defined" broadcasted messages to open/close the sidebar.
.directive("sidebar", function(){
return {
templateUrl: "sidebar.template.html",
link: function(scope, element){
scope.$root.$on("openSidebar", function(){
// whatever you do to actually show the sidebar DOM content
// e.x. element.show();
});
}
}
});
Then, a button could invoke a function in some controller to open a sidebar:
$scope.openSidebar = function(){
$scope.$root.$emit("openSidebar");
}
Another approach is to use a $sidebar service - this is somewhat similar to how $modal works in angularui-bootstrap, but could be more simplified.
Well, if you have a directive on a button and the element you need is outside the directive, you could pass the class of the element you need to toggle as an attribute
<button my-directive data-toggle-class="sidebar">open</button>
Then in your directive
App.directive('myDirective', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
angular.element('.' + attrs.toggleClass).toggleClass('active');
}
};
}
You won't always have the link element argument match up with what you need to manipulate unfortunately. There are many "angular ways" to solve this though.
You could even do something like:
<div ng-init="isOpen = false" class="sidebar" ng-class="{'active': isOpen}" ng-click="isOpen = !isOpen">
...
</div>
The best way for directive to communicate with each other is through events. It also keeps with the separation of concerns. Your button could $broadcast on the $rootScope so that all scopes hear it. You would emit and event such as sidebar.open. Then the sidebar directive would listen for that event and act upon it.
I am working on converting a html to angular js and one of the issue i have is, a button on the page uses ID and based of that id there is a div class that runs set of texts to be displayed accordingly.
Code that we have is something like this.
Continue
From the HTML page when the user clicks on the button continue... below code will be executed.
<div class="ContinueClicked">
text.......
</div>
I am trying to figure out a way to see how i can make it work with angular js. So when the user is clicking on the continue button, the page should display the content in div continueClicked. Should i be using any directive here? please help.
You have to adhere to AngularJS principles and conventions. Angular uses Directives for most of the DOM transformations, and Bindings for constant DOM and Model updates (two-way data bindings.)
In your case scenario you might want to have the following DOM elements (inside a Controller inside an ng-app Module, see AngularJS docs):
<!-- The button with the event handler as ng-click directive -->
<button ng-click="isContinue = true">Show continue content</button>
<!-- The content wrap with ng-show directive -->
<div class="ContinueClicked" ng-init="isContinue = false" ng-show="isContinue">
My content to be shown
</div>
You can also read and practice basic concepts following the Angular Tutorial.
Is it possible to create an element that will be used as an anchor in polymer. So for example
<template repeat="{{ content in contentitems }}">
<div id="{{ content.id }}">{{content.stuff}}</div>
</template>
Would it be possible to create a hyperlink to the content#id anchor like http://example.com/#someid
Alternatively, we can query that element with querySelector like the below and then scroll it into view if necessary with JavaScript. I'd rather not have to use a JS router however for anchor hyperlinking?
scrollIntoViewFunc(document.querySelector("html /deep/ #someid"))
Here's an actual URL I want to get working: http://megawac.github.io/status-whiskey/#status-408
The Web Component gods (aka Blink engineers) have decided that anchors inside of shadow-roots will not automatically scroll into view like they do in the main document. For this reason, I believe you will have to do something like you showed to handle this in JavaScript.
After brief searching, I couldn't find a reference to this question in the spec, it really needs to be spelled out somewhere.
If you come up with general solution, elementize it and share it back to the community. =P
Let's say you have a simple-element with some child elements with ids as anchors:
<simple-element>
<div id="anchor1"></div>
<div id="anchor2"></div>
</simple-element>
Then you can make a function to scrollIntoView when the hash changes:
window.addEventListener('hashchange', function() {
let targetElement = document.querySelector('simple-element').$[location.hash.substr(1)];
if(targetElement) {
targetElement.scrollIntoView();
}
}, false);
If I have this html:
<div id="myDiv"></div>
and this CSS:
#myDiv{
background:url('../images/someImage.png') no-repeat;
background-size:100%;
width:44px;
height:44px;
}
I need to open a new page when the user taps on myDiv. I have an external js file where I have this:
function bindMyDiv(){
$("#myDiv").bind('tap',function(event, ui){
alert("binding");
})
}
But I don't understand where to call this from the HTML, or if this is even the right way to go about this. Advice?
Try
$("#myDiv").live("tap", function(event){
alert('binding');
});
You can place this in side your onReady javascript file
EDIT:
http://jsfiddle.net/R9e6u/
Everyone here provided pretty good insight on different solutions for you to handle your script, but I don't think that anyone stopped to think SHOULD they help improve your script. "or if this is even the right way to go about this ", the answer is no. And perhaps I'm over-simplifying, but with JQM if you're trying to have a div (or any DOM element for that matter) open a new page simply wrap an anchor tag around around it (or in it, whichever is appropriate) and set your href to href="#myNewPage"and the id on the JQM page that you want to load to id="myNewPage"
jQuery Mobile's frame work is set up to automatically inject JS & AJAX into normal HTML elements to provide a smooth UX. While binding a touch event is sometime needed, this situation doesn't warrant that level of code...thats the beauty of jQuery Mobile =).
Examples of when to bind a touch event: show/hide a dom object, trigger a click for a plug-in etc.
You want to call that function on the pageinit event for the page on which it resides. You could use some other page-events from jQuery Mobile like: pagecreate, pageshow, etc. but I think pageinit is your best-bet.
The implementation would look something like this:
$(document).delegate('#page-id', 'pageinit', function () {
$("#myDiv").bind('tap',function(event, ui){
alert("binding");
})
});
OR
$(document).delegate('#page-id', 'pageinit', bindMyDiv);
You would replace #page-id with the ID of the data-role="page" element in which your div resides.
This method is preferred over event delegation for the #myDiv element because binding directly to an element creates less overhead when the event is triggered. If you use event delegation then the event has to bubble-up to the delegation root.