Ember.js anchor link

后端 未结 7 1065
时光说笑
时光说笑 2020-12-08 05:22

I have a login box on homepage that I need to link to. The login box has id=\"login\" in html and I have a link to it like this

  • 相关标签:
    7条回答
    • 2020-12-08 05:44

      If anyone's trying to solve this problem with Ember 3, I've got a solution. It makes use of the same queryParams approach as others have mentioned, but I couldn't get anything to work on the controller. The only approach that I found worked was to use the route + jQuery.ready function.

      // route/application.js
      import Route from '@ember/routing/route';
      import $ from 'jquery';
      
      export default Route.extend({
        queryParams: {
          anchor: null
        },
      
        setupController: function(controller, context, params) {
          let anchor = params.queryParams.anchor;
      
          // On ready, find the anchor offset and go there
          $().ready(function() {
            let anchorOffset = $("#" + anchor).offset().top
            window.scrollTo(0, anchorOffset);
          });
        }
      });

      Then in the template, use your queryParams as usual:

      {{#link-to "path.to.page" (query-params anchor="my-anchor")}}My Link{{/link-to}}

      Only issue here is that it's reloading the page every time, but apart from that seems to work - hope it helps someone.

      0 讨论(0)
    • 2020-12-08 05:56

      My problem was that if I clicked on the destination link from another page, it would go to the destination but not scroll down to the correct portion of the page. After a few hours here was my fix:

      note: I'm using ember-cli, and emblem and ember 1.8

      link in my navigation bar (in application.emblem)

      li 
       a#concept-link click=jumpToConcept
        | Le Concept 
      

      then if I'm already on page I just scroll up. If I'm not already on page then I go to that page with query params concept=true

      action in application controller

      scrollToConcept: function() {
        Ember.$(document).ready(
          Ember.$('html, body').animate({
              scrollTop: Ember.$("#concept").offset().top
          }, 750)
        )
      },
      
       //allow clicking of link with specific id to go to that part of page
      jumpToConcept : function(){
        if (this.get('currentPath') === 'index') {
          this.send('scrollToConcept');
        } else {
          this.transitionToRoute('index', { queryParams: {concept: true}});
        }
      }
      

      in index controller I then add the concept query params

      export default Ember.Controller.extend(
      
        queryParams: ['concept'],
        concept: null
      }
      

      I then add a scrollToConcept event in index view (the page I just went to) that listens for page loading and checks the concept queryParam. If concept=true I then scroll to the concept part of the page.

      index view

      scrollToConcept: function() {
          if (this.controller.get('concept') === 'true') {
              Ember.$('html, body').animate({
              scrollTop: Ember.$("#concept").offset().top
          }, 750);
          }
      }.on('didInsertElement')
      

      then for normal index links, I add an action that sets concept=null so that the concept query param doesn't show up in the url.

      link in nav bar

      a click=goToIndex
        h3 id={logoClass} Happy Dining
      

      then in application controller I go the the index route, set the concept query param to null (so it doesn't show up in the url) and scroll to the top (just incase it was lower on the page)

      actions: {
       goToIndex: function() {
        this.transitionToRoute('index', { queryParams: {concept: null}});
        Ember.$(window).scrollTop(0);
       }
      }
      

      Hope that helps people in the future!!!

      0 讨论(0)
    • 2020-12-08 06:01

      The problem with most of the previous answers is that if the route does not change when clicking on a "link" with a "href hash/fragment/id" in it then the ember router will not fire the hooks necessary to perform most of previous solutions.

      This is evident in pages with multiple "headings" where you want to allow a user to jump from a "nav/index or list of links" to the relevant section of the page (like on terms of service or about pages).

      In these situations ember requires that you "opt into a full transition" so that the router will fire it's hooks even though the route has not changed but the query params have. See "opting into a full transition" for more information.

      NOTE: The only documented hook that will be fired when using this "opt in" is the model hook.

      I believe that this "full transition" opt-in was only intended to be used when refreshing models on query param change for things like sorting or filtering.

      Admittedly this seems like a bit of a hack, but the above "opt-in" can be used for scrolling to our div /anchor tag in question. In the future the opt-in might be able to fire other more appropriate hooks as well (setupController specifically would be nice).

      Also In case anyone else is googling. I also tried using the "willTransition" and "didTransition" actions on the route as well. While they did get fired when transitioning from other routes sadly they also fail to fire when transitioning from the same route to itself.

      Finally it should be obvious to some (but wasn't for me at first) that in order to get the browser to scroll to the id in question the dom will need to be fully loaded. So we have to perform the scroll inside the Ember.run.schedule('afterRender', callback.

      FYI I am using the latest ember-cli, ember.js and ember-data generally available at the moment:

      • ember-cli: 1.13.7
      • ember: 1.13.6
      • ember-data: 1.13.7

      app/router.js

        this.route('about', {
          queryParams: ['anchor']
        });
      

      routes/about.js

      import Ember from 'ember';
      
      export default Ember.Route.extend({
        queryParams: {
          anchor: {
            refreshModel: true
          }
        },
        model: function(params) {
          var aboutController = this.controllerFor('about');
          aboutController.set('anchorLocation', params.anchor);
        }
      });
      

      app/controllers/about.js

      import Ember from "ember";
      export default Ember.Controller.extend({
        queryParams: ['anchor'],
        anchor: '',
        showAnchor: function() {
          var _this = this;
          Ember.run.schedule('afterRender', function scrollToAnchor(){
            var elem = Ember.$(_this.anchorLocation);
            elem.get(0).scrollIntoView(true);
          });
        }.observes('anchorLocation'),
      });
      

      app/templates/footer.js

                <ul>
                  <li>
                    {{#link-to "about" (query-params anchor='#contact')}}Contact{{/link-to}}
                  </li>
                  <li>
                    {{#link-to "about" (query-params anchor='#support')}}Support{{/link-to}}
                  </li>
                  <li>
                    {{#link-to "about" (query-params anchor='#team')}}Team{{/link-to}}
                  </li>
                </ul>
      
      0 讨论(0)
    • 2020-12-08 06:05

      Query Params

      Updated answer based on the Query Params approach (currently featured flag as of Dec 21 2013)

      Based on alexspellers original JSFiddle, complete demo can be found here: http://jsfiddle.net/E3xPh/

      In your Router, add support for query params

      App.Router.map ->
        @resource 'index', path: '/', queryParams: ['anchor']
      

      Using the Route of your choice, setup a property for the anchor query param in the setupController method.

      App.IndexRoute = Em.Route.extend
        setupController: (controller, context, queryParams) ->
          controller.set 'anchorLocation', queryParams.anchor
      

      Finally in your Controller make an observer for the anchorLocation property.

      App.IndexController = Em.ArrayController.extend
        showAnchor: (->
          $elem = $(@anchorLocation)
          $scrollTo = $('body').scrollTop($elem.offset().top)
        ).observes 'anchorLocation'
      

      Now you can use the following code in your templates to scroll to an anchor or point your browser to /#/?anchor=#login for example.

      {{#linkTo anchor='#login'}}Show login{{/linkTo}}
      

      Simple action approach

      Possible answer based on what you wrote in the comments to the first answer. Hacked together something simple here.

      http://jsbin.com/osEfokE/11

      Clicking the Index link takes you to the IndexRoute and scrolls you to the login box, however the URL is not reflecting this change and typing #login will not work either.

      App.ApplicationRoute = Ember.Route.extend({
          events: {
              goToLink: function(item, anchor) {
                  var $elem = $(anchor);
                  var $scrollTo = $('body').scrollTop($elem.offset().top);
      
                  this.transitionToRoute(item.route).then($scrollTo);  //.transitionTo is depricated
              }
          }
      });
      

      Instead of using linkTo, you will use goToLink in your template when you want to scroll to an anchor.

      <ul>
        <li><a href="#/" {{action goToLink "index" "#login"}}>Index</a></li>
        <li>{{#linkTo about}}About{{/linkTo}}</li>
        <li>{{#linkTo contact}}Contact{{/linkTo}}</li>
      </ul>
      
      0 讨论(0)
    • 2020-12-08 06:07

      The problem is that Ember used the hash part in the URL to store the current state of your application. Spontaneously i see two possible solutions.

      1 - *Don't let Ember use the hash part of your URLs.* Therefore use the HTML5 history location implementation of Ember. This will result in URLs like yourdomain.com/users/1/ without #.

      App.Router.reopen({
        location: 'history'
      });
      

      2 - Don't use this technique. Instead use jQuery to do the scrolling to the relevant part. This could look like this:

      <ul class="nav navbar-nav pull-right">
        <li><a {{action jumpToLogin}}>Signup</a></li> 
        <li>{{#linkTo 'about'}}About{{/linkTo}}</li>
      </ul>
      

      And in the corresponding view:

      App.YourView = Ember.View.extend({
        jumpToLogin : function(){
          $('html, body').animate({
              scrollTop: $("#login").offset().top
          }, 2000);
        }
      });
      

      This may seem a lot of code for this small feature, but i guess this is a nicer user experience right? Actually you can improve this approach by extracting this logic into a mixin, so you don't have to repeat it over and over:

      App.ScrollToMixin = Ember.Mixin.create({
        scrollDuration : 2000, //default
        scrollTo : function(selector){
          $('html, body').animate({
              scrollTop: $(selector).offset().top
          }, this.get("scrollDuration");
        )
      });
      // mix it into your View
      App.YourView = Ember.View.extend(App.ScrollToMixin, {});
      

      And use it in your template:

      <ul class="nav navbar-nav pull-right">
        <li><a {{action scrollTo "login"}}>Signup</a></li> 
        <li>{{#linkTo 'about'}}About{{/linkTo}}</li>
      </ul>
      

      PS: I haven't tested the code with the mixin. I am not absolutely sure wether the String "login" gets passed to the action handler exactly like that. So you would have to test :-)

      0 讨论(0)
    • 2020-12-08 06:08

      I use a component, which could also be extended to support query params via an action.

      var ScrollToComponent = Ember.Component.extend({
        tagName: 'a',
        anchor: '',
      
        scrollTo: function () {
          var anchor = this.get('anchor'),
            $el = Ember.$(anchor);
      
          if ($el) {
            Ember.$('body').scrollTop($el.offset().top);
          }
        }.on('click')
      });
      

      This is how you'd use it:

      {{#scroll-to anchor=anchor}}Jump To Anchor{{/scroll-to}}
      

      Where anchor is #my-id.

      Edit

      Here's an ember-cli addon that does this https://www.npmjs.com/package/ember-scroll-to

      0 讨论(0)
    提交回复
    热议问题