Настройте ui-router с компонентами, содержащими несколько привязок

0

Я пытаюсь найти лучшее решение для использования ui-router вместе с angular components.

Рассмотрим две простые компоненты:

app.component('componentOne', {
  template: '<h1>My name is {{$ctrl.name}}, I am {{$ctrl.age}} years old.</h1>',
  bindings : {
      name : '@',
      age : '@'
    }
  }
);

app.component('componentTwo', {
  template: '<h1>I am component 2</h1>'
});

Прямо сейчас я указываю компонент и его параметр, используя свойство template:

 app.config(function($stateProvider, $urlRouterProvider ){
 $stateProvider
    .state('component1', {
      url: "/component1",
      template: "<component-one name=\"foo\" age=\"40\"></component-one>"
    })
    .state('component2', {
      url: "/component2",
      template: "<component-two></component-two>"
    })
});

Хотя это работает нормально, у меня есть компоненты с arround десять привязок, что делает конфигурацию ui-router очень неудобной.

Я попытался использовать свойство component но это не работает для меня вообще. Единственное другое решение, которое я нашел, - указать родителя с использованием свойства require и опустить привязки - но это мне не подходит... Есть ли лучший способ сделать это?

Вот plnkr.

Теги:
angular-ui-router
angular-components

3 ответа

1
Лучший ответ

component: UI-Router component: маршрутизация существует в UI-Router 1. 0+ (в настоящее время 1.0.0-beta.1)

Здесь обновленный плункер: https://plnkr.co/edit/VwhnAvE7uNnvCkrrZ72z?p=preview

Связывать статические значения

Чтобы связать статические данные с компонентом, используйте component и блок разрешения, который возвращает статические данные.

$stateProvider.state('component1', {
  url: "/component1",
  component: 'componentOne', 
  resolve: { name: () => 'foo', age: () => 40 }
})

Связывать значения async

Чтобы привязать значения async, используйте решение, которое возвращает обещания для данных. Обратите внимание, что одно решение может зависеть от другого решения:

$stateProvider.state('component1Async', {
  url: "/component1Async",
  component: "componentOne",
  resolve: {
    data: ($http) => $http.get('asyncFooData.json').then(resp => resp.data),
    name: (data) => data.name,
    age: (data) => data.age
  }
});

Привязать множество значений

Вы упомянули, что у вас есть 10 привязок к компоненту. В зависимости от структуры данных, которые вы связываете, вы можете использовать JavaScript для построения блока resolve (в конце концов, это "просто javascript")

var component2State = {
  name: 'component2',
  url: '/component2',
  component: 'componentTwo',
  resolve: {
    data: ($http) => $http.get('asyncBarData.json').then(resp => resp.data)
  }
}

function addResolve(key) {
  component2State.resolve[key] = ((data) => data[key]);
}

['foo', 'bar', 'baz', 'qux', 'quux'].forEach(addResolve);

$stateProvider.state(component2State);
  • 0
    очень хорошо. Позвольте мне попробовать это завтра.
1

Одна из альтернатив, которую вы можете попробовать, - переопределить шаблон пользовательскими свойствами состояний в событии $stateChangeStart.

Выполните блок, подобный этому, для достижения такого поведения.

app.run(function($rootScope){

    //listen to $stateChangeStart
    $rootScope.$on("$stateChangeStart",function(event, toState, toParams, fromState, fromParams, options){

    //if the component attribute is set, override the template
    if(toState.component){


      //create element based on the component name
      var ele = angular.element(document.createElement(camelCaseToDash(toState.component)));

      //if there is any binding, add them to the element attributes.
      if(toState.componentBindings){
        angular.forEach(toState.componentBindings,function(value,key){
          ele.attr(key,value)
        })
      }

      //you may also do something like getting bindings from toParams here

      //override the template of state
      toState.template = ele[0].outerHTML;
    }


  })

  //convert camel case string to dash case
  function camelCaseToDash(name) {
    return name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
  }

})

И с этим теперь вы можете иметь свойство component в своей конфигурации состояния.

app.config(function($stateProvider, $urlRouterProvider ){
 $stateProvider
    .state('component1', {
      url: "/component1",
      component:"componentOne",
      componentBindings:{
        name:"foo",
        age:"40",
      }
    })
    .state('component2', {
      url: "/component2",
      component:"componentTwo",
    })
});

Вот рабочий плункер.

Тем не менее у вас может быть большая функция конфигурации, но это будет выглядеть не так уж неудобно.

  • 0
    Спасибо за это, конфиг теперь выглядит намного чище. Я прыгал, чтобы найти встроенное решение, но если никто не придет с лучшим подходом, я приму ответ через несколько дней.
1

Кроме того, вы можете переместить свои привязки на уровень вниз и создать объект, который будет единственным привязкой. Если 10 привязок - это то, что вас беспокоит.

  • 0
    Да, это тоже сработало бы +1. Но не совсем то, что я искал.
  • 0
    Понимаю. Или есть templateUrl, который делает настройку менее неудобной.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню