Pass object to component - angularjs

I have created a component that needs to have a reference to the object for which the component was created. I didn't make to work and all my trials have failed. Below, I try to describe the intention.
The component definition would maybe look like this:
angular
.module('myModule')
.component('myComponent', {
templateUrl: "template.html",
controller: [
MyController
],
bindings: {
myObject: '='
}
});
function MyController(myObject) {
var vm = this;
vm.myObject = myObject;
}
In a service I would like to create my object like this:
function createMyObject(args) {
var myObject = {some: data};
myObject.ref = "<my-component myObject='{{myObject}}'></my-component>";
return myObject;
}
Question
How can I pass data to angular component tag? Do I have to switch back to a component directive to make it work?
Any ideas are greatly appreciated. Thank you.

Solution 1
In your template:
<my-component key='$ctrl.myObject'></my-component>
In code:
angular
.module('myModule')
.component('myComponent', {
templateUrl: "template.html",
controller: [
'objectService'
MyController
],
bindings: {
key: '=' // or key: '<' it depends on what binding you need
}
});
function MyController(myObject, objectService) {
var vm = this;
vm.myObject.whatever(); // myObject is assigned to 'this' automatically
}
Solution 2 - via Component Bindings
Component:
angular
.module('myModule')
.component('myComponent', {
templateUrl: "template.html",
controller: [
'objectService'
MyController
],
bindings: {
key: '#'
}
});
function MyController(myObject, objectService) {
var vm = this;
vm.myObject = objectService.find(vm.key);
}
Usage:
function createMyObject(args) {
var myObject = {key: ..., some: data};
myObject.ref = "<my-component key='" + myObject.key + "'></my-component>";
return myObject;
}

Related

Unable to pass data to a controller inside a component in AngularJS

I have following component
componentsModule.component('detailComponent', {
templateUrl: 'detailTemplate.html',
scope: {},
bindings: {
textParam: '='
},
controller: ['$mdDialog', function($mdDialog) {
this.textParam // this is undefined always
}]
});
I am loading template in a dialog from other controller like this
$scope.textParam = tParam;
const parentEl = angular.element(document.body);
$mdDialog.show({
template: '<detail-component text-param="$scope.textParam"></detail-component>',
ariaLabel: 'detailComponentDialog',
parent: parentEl
}).then((savedDatails) => {});
If I use binding as # then I get $scope.textParam as a string inside my controller in this.textParam but if I set binding as < or = then I get undefined

Can't add an attribute to an element using $postLink - AngularJS

I have a simple component and what I'm trying to do is to add to my input element an attribute multiple dynamically but somewhy it doesn't work. Why? And is there any way to do what I want?
app.component('myComponent', {
templateUrl: 'tmpl.html',
bindings: {
str: '#'
},
controller: function () {
var ctrl = this;
ctrl.$postLink = function () {
$('#myInputId').attr('multiple', '');
}
}
}
This is the solution:
app.component('myComponent', {
templateUrl: 'tmpl.html',
bindings: {
str: '#'
},
controller: function ($element) {
var ctrl = this;
ctrl.$postLink = function () {
$element.find('input').attr('multiple', 'multiple');
}
}
}
The trick was in linking stuff. Code from the question doesn't work because the input not exists in DOM yet at the time $postLink hook triggered. So what we need is to inject $element service into controller and use it to manipulate DOM.

Angular js binding "<" give undefined inside controller

I have "invite-friends-code" component which get data through binding "<". The problem is, it is pass correctly and show in the view directly, but when i trying to munipulate with it inside "invite-friends-code" controller it gives me "undefined"
component
const inviteFriendsCodeComponent = {
bindings: {
leagueCode: '<'
},
templateUrl: '/js/common/invite-friends-code/invite-friends-code.html'+assetsVersion,
controller: 'InviteFriendsCodeController'
}
binding using inside other component view:
<invite-friends-code league-code="$ctrl.leagueData.code"></invite-friends-code>
controller:
ctrl.$onInit = () => {
console.log(ctrl.leagueCode) // gives me undefined here
}
Your bindings are not initialized yet!
You can use $onInit function.
app.component('yourComponent', {
bindings: {
leagueCode: '<'
},
controller: function() {
var ctrl = this;
this.$onInit = function() {
console.log(this.leagueCode)
});
}
}
Official doc

How to use resolve with Angular 1.5 *components* and UI Bootstrap Modal

I am trying to pass data to a ubi modal that is an Angular 1.5 component using resolve. I know this is possible because it shows that resolve is supported for components in the uib modal documentation.
component (Type: string, Example: myComponent) - A string reference to
the component to be rendered that is registered with Angular's
compiler. If using a directive, the directive must have restrict: 'E'
and a template or templateUrl set.
It supports these bindings:
(...)
resolve - An object of the modal resolve values. See UI Router
resolves for details.
All the examples I am finding declare templateurl/controller in the open method. Then the item declared in resolve is injected into to the controller. I am passing an Angular 1.5 component to the modal (not templateurl/controller), and when I try to inject the item from resolve, I get a dreaded "unknow provider" error.
Here is my code. I am trying to pass a url.
Controller of component calling the model
ParentController.$inject = ['$uibModal'];
function ParentController $uibModal) {
var $ctrl = this;
$ctrl.openComponentModal = function(url) {
var modalInstance = $uibModal.open({
animation: false,
component: "ImageModalComponent",
resolve: {
url: function() {
return url;
}
}
});
};
}
Controller in component that is the modal
ImageModalController.$inject = ['url'];
function ImageModalController(url) {
var $ctrl = this;
$ctrl.$onInit = function() {
console.log(url);
};
}
For components, resolve needs to be added to the bindings, then it is available on the isolated scope. In other words, add resolve: '<' when declaring the component.
Modal Component
var template = require('./image_modal.component.html');
var ImageModalController = require('./image_modal.controller');
module.exports = {
template: template,
bindings: {
close: '&',
resolve: ‘<‘
},
controller: ImageModalController
};
Controller of component calling the model
ParentController.$inject = ['$uibModal'];
function ParentController $uibModal){
var $ctrl = this;
$ctrl.openComponentModal = function (urlFromClickEvent) {
var modalInstance = $uibModal.open({
animation: false,
component: "ImageModalComponent",
resolve: {
url: function() {
return url;
}
}
});
};
}
Controller of component that is the modal
ImageModalController.$inject = [];
function ImageModalController() {
var $ctrl = this;
$ctrl.$onInit = function () {
console.log($ctrl.resolve.url);
};
}

Angular: accessing directive attributes in controller constructor

(Using Angular 1.5)
I am trying to use the following design pattern for my angular app:
angular.module("app").directive("MyDirective", MyDirective);
function MyDirective () {
return {
bindToController: {
someId: "=",
otherAttr: "#"
},
controller: ["$attrs", MyController],
controllerAs: "ctrl"
};
}
function MyController ($attrs) {
var self = this;
console.log(self);
console.log($attrs);
}
I use my directive in my HTML like this:
<my-directive someId="someParentScope.model._id" otherAttr="1">
In the console, for self I see:
Object { otherAttr: undefined, someId: undefined }
and for $attrs I see:
Object { $attr: Object, $$element: Object, otherattr: "1",
someid: "someParentScope.model._id", otherAttr: undefined, someId: undefined,
$$observers: Object }
How may I accomplish what I am trying to accomplish (i.e. passing data from parent scope into my directive controller constructor), and why is even my single binding ("#" binding) otherAttr undefined in the controller constructor? Is this design pattern is flawed/misguided? Thanks!
looks like you have the naming conventions wrong on the directive, you should define the name on directive attribute as "data-content" and use on the controller as "dataContent"
Take a look this demo i've done
// directive HTML
<my-directive some-id="name" other-attr="1"></my-directive>
//app.js
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
});
app.directive('myDirective', function() {
return {
restrict: 'E',
bindToController: {
someId: "=",
otherAttr: "#"
},
controller: ["$attrs", MyController],
controllerAs: "ctrl"
}
});
function MyController ($attrs) {
var self = this;
console.log(self);
console.log($attrs);
}
http://plnkr.co/edit/P3VKdO?p=preview

Resources