I wrote a sliding panel directive and I can't figure out how to have multiple instances of the directive on a page. I am passing in a panel-id attribute to the directive and I need to figure out how to use that id to trigger the correct panel instance. I have a codepen here:
http://codepen.io/mcastre/pen/Ejzebd
Thanks!
What you can do is have the individual directives register themselves with the panelService on link (add a method called registerPanel(scope) to the service for example).
Then your controller methods like toggleWeightPanel() just need to pass in the id that identifies your panel and it can search through the scopes of all registered panels to find the matching one, and call the appropriate method on it.
Somewhere in your controller scope you should keep a list of panel ids that you can use in your ng-click directives and pass down into your panel directives.
Does that make sense?
You really shouldn't need a service for this. A simple true/false param in your code and an ng-show="ShowMe". And in your code set $scope.ShowMe = true;
Related
I have an AngularJS app, and on one of the pages, I have a number of widgets, each one displaying some information about the status of a part of the system.
I am currently working on adding the functionality to allow the user to 'hide' the heading of a given widget.
There is a 'Settings' button on the page where the widgets are displayed, which, when clicked, overlays a toolbar on top of each of the widgets. The toolbar has a number of buttons- one of which is another 'Settings' button, which opens up a dialog that allows the user to change the settings for that particular widget.
I have added a checkbox to the dialog, to enable the user to 'hide' the heading for that particular widget from view:
When the checkbox is selected on the dialog, and the user clicks 'Preview', I am expecting (eventually- I'm still working on the implementation of the feature) the heading for that particular widget to be hidden. However, currently, when the user clicks 'Preview', whether the checkbox is selected or not, I am getting an error in the console that says:
TypeError: $scope.widget.toggleWidgetHeading is not a function
This error is coming from the $scope.preview function in ctrl.js called when the 'Preview' button is clicked on the dialog:
}).controller('WidgetPickerCtrl', function($scope, $timeout, fxTag, gPresets, appWidget) {
...
$scope.preview = function(e) {
$scope.widget.toggleWidgetHeading();
...
};
...
});
I don't understand why I'm getting this console error, since toggleWidgetHeading() clearly is a function...
If I right-click on the function call above in Sublime, and select 'Go to definition', I am taken to the directive.js file where the function is defined:
.directive('appWidget', function($timeout, fxTag, appColorFilter) {
return {
...
link: function($scope, $element){
...
var toggleWidgetHeading = function(){
...
}
...
}
}
})
Also, clicking the 'Preview' button on the dialog no longer closes the dialog...
Why is it that I'm being told that this function call is not a function when it is clearly defined as one? Is the issue here something to do with the scope (i.e. the fact that I'm calling the function from ctrl.js, even though it's defined in directive.js)?
The definition of your directive, where you added ..., is actually a really relevant part about directives scopes.
Directives can implement several kind of scopes. You can actually inherit and access the parent scope, or you can have an isolated scope for example.
You may read about that in the official documentation where is well explained:
https://docs.angularjs.org/guide/directive
However, whatever will be the scope you use, by default AngularJS implements the inheritance of scopes, as usually inheritance works: children can access parent methods, but parent cannot access children's methods.
Here it seems that from the parent scope (the controller) you are trying to access the directive's scope, which is actually no possible. (even if in the link function you define the toggleWidgetHeading as private variable, and not associated to the $scope itself - but it won't work either).
So you have few options in these cases:
Define your "visible properties" inside a service and inject the service inside the directive and the controller. Then use the service in order to access and change these values, so that they will be sync between the controller and the directive
Add a scope parameter to the directive as callback & and provide a function from the controller which returns the chosen visibility of the widget, so from the directive you can call that function and get back the value of widget's visibility
Add a scope parameter as two way data binding = in the directive, which is bound to the widget's visibility of the controller, so that you have that always sync between your controller and your directive
Use events in order to communicate between the controller and the directive, broadcasting an event from the controller when the visibility changes, and reading the event from the directive getting the widget's visibility value
I hope it makes sense
In fact, I want to ask how to make use ngModel.NgModelController's method and properties within the controller, and it will be perfect if there is more explaination about the usage of ngModel.NgModelController instead of giving the link of the api to me? What I have faced, is I want to set something like the following works within my controller. More precisely, I want to make the option with "--- please fill in ---" 's text to disappear once the droplist is clicked, but I want to do the operation at the controller instead of like the example below. To split off my question, there are several pieces I am interested in:
How do I set up the object used for the form (as I am doing a form) at both the controller and the HTML template
How do I set up the corresponding objects to each of the form field, like the select field below in both the controller and the HTML template
What else should I know to solve the question?
<select name="dropdown"
ng-model="$ctrl.value"
ng-options="o.id as (o.state) for o in $ctrl.form.stateCode.options">
<option ng-if="!form.dropdown.$touched" value=""> --- please fill in --- </option>
</select>
P.S. I don't know whether because I am using requireJS together with angular, so the $ctrl may actually representing the scope of the controller.
In angular when you are using forms it is more recommended that you should use form tag with a name attribute so that angular binds that form to the current controller scope.
and after that when you are using input with in that form then the input that are using ng-model directive, that input controller will be bind to the formcontroller. Here I am attaching a fiddle http://jsfiddle.net/WdVDh/79/
$ctrl is not same as $scope. When we are using controller as syntax, then angular binds the $ctrl property to the $scope
For more info on this you should go for https://docs.angularjs.org/guide/forms
I have created tab controls and each tab is using different controller. Each tab has some input types and also it has got validations. I have used form for each tabs and different controller for each tabs. I want to validate the form when i click on another tab. For example if there is any invalid value in Tab 1 then when user clicks on Tab 2 it should validate Tab 1 and if any invalid value is found then it should focus the invalid field and do not allow to switch tabs. Switching of tabs should be allowed only when form in the tab is valid.
Now i am not able to check whether form is valid or not during tab switch because tab DOM is out side the form and its controller. So i cant access formname.$valid property. So how i can handle this scenario?
Here is sample plunker
In plunker example, you have used different form for different template and included using ng-include. Instead you can make only one form and in individual template add only required form element instead of individual form. Use form validation on click event of specific tab and check whether input is valid or not. If input is not valid show error message and prevent switching from current tab to next tab.
Notes: Don't use ng-if for showing or hiding template instead use ng-show or ng-hide
while click on the second tab from second controller call controller of first tab and check form data is set or not.if not set call ng-click function of first tab.
we can communicate between two controllers using following ways\
1)sharing a data service
function FirstController(someDataService)
{
// use the data service, bind to template...
// or call methods on someDataService to send a request to server
}
function SecondController(someDataService)
{
// has a reference to the same instance of the service
// so if the service updates state for example, this controller knows about it
}
2)emit event on the scope
function FirstController($scope)
{
$scope.$on('someEvent', function(event, args) {});
// another controller or even directive
}
function SecondController($scope)
{
$scope.$emit('someEvent', args);
}
You can do this:
Step1: Inject the $rootScope service in the controllers.
Step2: Now make a $rootScope variable say $rootScope.validForm=false;
Step3: Now you can set/check in every controller
if(formname.$valid){
//Your code
$rootScope.validForm=true;
}else{
$rootScope.validForm=false;
}
Step4: set ng-disable="$root.validForm===false" in the html
You can play with this rootScoep variable to maipulate accordingly.
More over your structure is not correct make one form , also use ng-repeat for tab generation, need lot of improvements in your code.
I've written my own Angular directive called <my-table> since I use it multiple times, passing in different data to display. All of the tables have a button that when clicked, a popup form appears, like so:
However, for one of the <my-table> directives, I want to extend the behavior so that it acts slightly different from the other <my-table>s. For example, let's say that for the form that pops up, an alert box will appear when you click Submit, displaying data present in that <my-table>'s scope.
My question is, what is the best way extend the behavior of a given directive while still being able to access the directive's scope? Is this possible, or am I simply using directives incorrectly?
You can do something to this extent:
<my-table on-submit="doSomething(message)"></my-table>
In your my-table directive definition you would bind your callback to the scope:
scope: {
'submit': '&onSubmit'
},
Then in your controller you define your function:
$scope.doSomething = function(message) {
alert(message);
}
In your template, where you define the submit button, you would do:
<button ng-click="submit({message: 'bye!'})"></button>
You can reference angular's documentation for more info:
https://docs.angularjs.org/guide/directive
This seems super simple. but I can't figure out how its supposed to work.
I have a unordered list of items, which are built from an ng-repeat, which itself is based on a collection of data objects.
So in the DOM (in Jade):
div#projectListing
ul.sidebar-listing
li.sidebar-header Theatrical Projects
li.sidebar-item(ng-click="loadProject()", ng-repeat="project in theatricalProjects | orderBy:'title'") {{ project.title }}
Now I have a nice listing of items in my sidebar, but I want to be able to click one of these elements, and get the full model its tied to - project. What is the 'angular' method to handle this? Do I need to create a custom directive instead of using ng-click()? Do I need to assign an ng-model to each listing with a unique name?
Thanks.
I am assuming you need the respective project inside loadProject when clicked. You could just pass in the project as an argument to loadProject and accept it in your function definition:
li.sidebar-item(ng-click="loadProject(project)", ng-repeat="project in theatricalProjects | orderBy:'title'");
Basically ng-repeat will create a child scope for all the repeated element (li.sidebar) so all of those child scope will have the propery project associated to them and also from inside the method loadProject() you should be also able to access it using this.project