I'm having data in the form given below
var servers = [
{
"name": "server1",
"version":
[
"10.x"
]
},
{
"name": "server2",
"version":
[
"1", "2"
]
}
]
I want to have two drop down.
First dropdown will display "name".
When user selects name from the first dropdown, second dropdown should be populated with corresponding "version".
Non-working jsfiddle link: http://jsfiddle.net/fynVy/174/
You need to tweak your HTML template, so that the first drop down is displaying the server name, and that the options for the 2nd drop down are based upon the versions in the selected drop down (ngModel of the first drop down).
<div ng-controller="MyCntrl">
<select ng-model="server" ng-options="x.name for x in servers"></select>
<select ng-model="version" ng-options="val for val in server.version"></select>
</div>
working fiddle here
Related
Still in my very first days with Angular and ran into a problem i can't get my head around.
What I am trying to accomplish is sort of creating a way to have a persons name added to a message template.
The templates are loaded from a file like this
this.http.get('../../assets/templatefiles/customtemplates.json').subscribe(data => {this.templateArray = data as any [];
The structure of the JSON file is as follows
[{
"Id": 1,
"Type": "SR Templates",
"Name": "Message 1",
"Body": "Some meaningful text here"
},
{
"Id": 2,
"Type": "SR Templates",
"Name": "Message 2",
"Body": "Some more meaningful text here"
},
{
"Id": 3,
"Type": "GTFO Templates",
"Name": "Message 3",
"Body": "Guess what? Exactly, some even more..blahhh"
}]
All good so far. Then, in my template I use ng-select to create the dropdown list to display the options grouped by Type
<ng-select [items]="templateArray"
bindLabel="Name"
bindValue="Body"
groupBy="Type"
[(ngModel)]="selectedTemplate"
>
<ng-template ng-optgroup-tmp let-item="item">
<strong>{{item.Id}}</strong>
</ng-template>
</ng-select>
So far...working it seems. Templates are grouped by Type and show up in the drop down just fine.
Below the selection is a textarea in which the "Body" value is supposed to be displayed. Works fine as well, when selecting a template from the drop down the text shows fine in the textarea.
The problem I am facing is that there is an input field for the persons name the message will be send to.
I get the name as follows:
<input type="text" [(ngModel)]="srcName" class="form-control" placeholder="Name">
The bit confusing me is how to get/add the persons name to the message using interpolation?
I was hoping for something like just having to change the text in the JSON and adding the interpolation to it but apparently that does not work hehe.
{
"Id": 1,
"Type": "SR Templates",
"Name": "Message 1",
"Body": "Dear {{srcName}, Some meaningful text here"
}
I've been searching up and down, but am ultimately stuck and am desperate for a nudge in the direction I would have to go to actually get that name inserted in the textarea together with the template from the array...
You can make a function that concatenates your selected template and the name in you input, like so:
onSubmit() {
this.message = `Dear ${this.srcName}, ${this.selectedTemplate}`;
}
And then you can add a button that executes this function:
<button (click)="onSubmit()">Submit</button>
Now whenever you select the template you want and add the name you want to the input and click on submit button, you will get a concatenated message with the info you want.
Here is a live demo if you want more explanation.
In the live demo a used a normal HTML select, but it should work the same with angular material select.
##EDIT
If you need to put your srcName inside of your templates body, you will have to create a place holder in your template's body, something like:
"Guess what? Exactly {srcName}, some even more..blahhh"
instead of:
"Guess what? Exactly, some even more..blahhh"
Then you will have to change the onSubmit function:
onSubmit() {
this.message = this.selectedTemplate.replace('{srcName}', this.srcName)
}
I also added the changes to to the live demo.
I am using ment.io plugin from http://jeff-collins.github.io/ment.io/#/examples with tinyMce for editor support.
All was well until i found that when i select menu item by using mouse, model is not updating automatically, though in editor it is showing selected text properly.
Further while investigation, found that model is updating when we do some key event inside editor after selection with mouse.
While select with arrow key and select using enter or tab, model is updating properly. This might be because, this is the key event which editor seeks in earlier case.
Here is link of fiddle for the scrnario https://jsfiddle.net/vikasnale/2p6xcssf/5/
<div ng-app="App">
<script type="text/ng-template" id="/tag-mentions.tpl">
<ul class="list-group user-search">
<li mentio-menu-item="Tag" ng-repeat="Tag in items" class="list-group-item">
<span class="text-primary" ng-bind-html="Tag.name | mentioHighlight:typedTerm:'menu-highlighted' | unsafe"></span>
</li>
</ul>
</script>
<textarea mentio-id="'tinyMceTextArea'" ui-tinymce="tinyMceOptions" mentio mentio-typed-text="typedTerm" mentio-require-leading-space="true" ng-model="Content" mentio-iframe-element="iframeElement"></textarea>
<mentio-menu id="hastmenu" mentio-for="'tinyMceTextArea'" mentio-trigger-char="'#'" mentio-items="tags" mentio-template-url="/tag-mentions.tpl" mentio-search="searchTags(term)" mentio-select="getTagTextRaw(item)"></mentio-menu>
<br/>
<p>Output Model: {{Content}}</p>
angular.module('App', ['mentio', 'ui.tinymce'])
.controller("Ctrl", ['$scope', 'mentioUtil',
function($scope, mentioUtil) {
$scope.getTagTextRaw = function(item) {
return '<i class="mention-tag-text" style="color:#a52a2a;">' + item.name + '</i>';
};
$scope.searchTags = function(term) {
var tagsList = [];
angular.forEach($scope.allTagList, function(item) {
if (item.id.toUpperCase().indexOf(term.toUpperCase()) >= 0) {
if (tagsList.length <= 5) {
tagsList.push(item);
}
}
});
$scope.tags = tagsList;
return tagsList;
};
$scope.allTagList = [{
"id": "ctp",
"name": "#ctp"
}, {
"id": "earningRelease",
"name": "#earningRelease"
}, {
"id": "presssrelease",
"name": "#presssrelease"
}, {
"id": "inversor-conference",
"name": "#inversor-conference"
}, {
"id": "live release",
"name": "#IACLive"
}, {
"id": "reval",
"name": "#reval"
}, {
"id": "margin",
"name": "#margin"
}, {
"id": "phonecall",
"name": "#phonecall"
}, {
"id": "Q4",
"name": "#Q4"
}];
$scope.tinyMceOptions = {
init_instance_callback: function(editor) {
$scope.iframeElement = editor.iframeElement;
},
resize: false,
width: '100%',
height: 150,
plugins: 'print textcolor',
toolbar: "bold italic underline strikethrough| undo redo",
toolbar_items_size: 'small',
menubar: false,
statusbar: false
};
}
]);
Note : This behavior is observed while using ment.io with tinymce
can't figure out the fix for this..
Please advice...
I faced the same problem and on search came across this post. Since there was no solution I thought I would dig deeper. Here are my findings, If you can add on top of this to find a solution it would be of great help.
(1) I am using MEAN framework with angularJS. And trying to implementMent.io with Tiny MCE
(2) Question: Why is it working with the codepen Ment.io example and not working with the implementation in jsfiddle ..
Answer or observation,
In the codepen implementation if you see they have included the tinymce but have never used it with the div.
also they have implemented a directive with listeners that is applied with ment.io called "contenteditable" this helps in properly replacing the values..
In the Jsfiddle example by Vikas Nale. The text area includes the tinymce editor. So as soon as we apply the Tinymce editor the model stops updating on enter key or mouse click, a space bar has to be pressed inorder for the model to be properly updates.
(3) probable reason Now I thought I will also add the contenteditable directive and it will take care of the events. But it seems that when we apply the tinymce editor, the mention menu, text area etc is placed in an iframe element. Because of which the events are not propagating correctly.
I also tried the Setup: option of tinymce. but as soon as we start that the # menu of Ment.io stops working.
this is as far as I could understand. I need to implement this in a project so any discussion, hint, pointers are welcome.
The above issue of not getting up to date text from the assigned data model was solved for me by getting the data from active editor of tinymce instead of the data model assigned to ment.io text area (see the attached screen shot).
I have the following data (provided from an Angular service, stored in the controller) I need to use to populate a drop-down, and also select the default value. When the page renders, the first dropdown option is "?" and is selected by default. The second dropdown option is "Name 1".
I've read around and tried different things, so I'm wondering if this is caused the track by being based on an id field with a different name (id vs. otherId)? Any ideas?
For the dropdown:
{"someDataSet":
[
{"id": "1", "name": "Name 1"},
{"id": "2", "name": "Name 2"}
]
}
For selecting the default value:
{"otherDataSet":
{"otherId": "1", "otherName": "Name 1"}
}
My front-end code:
<select ng-options="someData.name for someData in controller.someDataSet
track by someData.id" ng-model="controller.otherDataSet.otherId"/>
Thanks!
Check this solution: http://codepen.io/tzach/pen/LVKeGJ
Adding an option element will set the default value until your real data is loaded:
<option value="{{ controller.otherDataSet.otherId }}">{{ controller.otherDataSet.otherName }}</option>
I'm banging my head on the wall over this for days and finally decided to post this question since I can't find an answer that matches what I'm trying to do.
Context: I'm building a dynamic form building platform that describes form elements in a JSON structure like this -
{
"name": "email",
"type": "email",
"text": "Your Email",
"model": "user.profile.email"
}
And then in the View I have a recursive ng-repeat that includes the field template like this -
<script type="text/ng-template" id="field.html">
<div ng-if="field.type === 'email'" class="{{field.class}}">
<p translate="{{field.text}}"></p>
<input type="{{field.type}}" name="{{field.name}}" class="form-control" dyn-model="{{field.model}}">
</div>
</script>
As you see, I use a custom directive dynModel to create the ng-model attribute with interpolated value of the model from the string value. So far do good.
Now I have a more complex scenario in which I have a collection of fields that can be added or removed by clicking on Add button or removeMe button. See below -
{
"name": "urls",
"type": "collection",
"text": "Your Profile URLs",
"model": "user.profile.urls",
"items": [
{
"name": "url",
"type": "url",
"text": "Facebook URL",
"model": "url"
},
{
"name": "url",
"type": "url",
"text": "Facebook URL",
"model": "url"
}
],
"action_button": {
"name": "add",
"type": "action",
"action": "addURL"
}
}
<div ng-if="field.type === 'collection'">
<button class="btn btn-info" dyn-click click-action="{{field.action_button.action}}" click-model="{{field.model}}">{{field.action_button.text}}</button>
<div dyn-ng-repeat="item in {{field.model}}" >
<div ng-repeat="field in field.items" ng-include src="'field.html'"></div>
</div>
</div>
As you'll notice, I have another custom directive that takes care of interpolation of {{field.model}} from the previous ng-repeat (not shown).
Now to the crux of the issue. As you see in the template, I have nested ng-repeats, the first one iterates through user.profile.urls and the second one iterates through the field parameters in JSON and creates the HTML tags, etc. One of those fields is a button (action_button) that is used to add more URLS to the list. When I click the button, I want it to trigger a function in my controller and effectively add a new child to the parent model (user.profile.urls). I then also want each URL, existing and new to have a remove button next to them that will be dynamic and will remove that particular item from the model.
If you see the code above, I have a custom directive dyn-click that reads in the
click-action="{{field.action_button.action}}"
That contains the function name (addURL) to be called that resides in my controller and the model
click-model="{{field.model}}"
(user.profile.urls) to which the new item is to be added. This is not working. The reason for this complexity is that I have multiple levels of nesting and at each level there are dynamic elements that need to be interpolated and bound. The directive dyn-click looks like this right now -
exports = module.exports = function (ngModule) {
ngModule.directive("dynClick",function() {
return {
restrict: 'A',
link: function(scope,element,attrs) {
$(element).click(function(e, rowid){
scope.clickAction(scope.clickModel, scope.$index);
});
}
};
});
};
With this code, when I click on the rendered form's Add button, the code in the $(element).click method above gets executed giving the following error -
Uncaught TypeError: undefined is not a function
I have tried a few different things with scope:{} in the dyn-click directive, with different errors and none of them have worked completely with two way binding of the model and calling the function as expected.
Help!
EDIT-1 - please see the comments:
$(element).click(function(e, rowid){
scope.$eval(attrs["clickAction"])(scope.$eval(attrs["clickModel"]), scope.$index);
});
EDIT-2: The plunker is here - http://plnkr.co/edit/DoacjRnO61g4IYodPwWu?p=preview. Still tweaking it to get it right, but you guys should be able to see the necessary pieces. Thanks!
EDIT-3: Thanks Sebastian. The new plunker is here - http://plnkr.co/edit/Z6ViT7scubMxa17SFgtx?p=preview . The issue with the field.items ng-repeat still exists. For some reason the inner ng-repeat is not being executed. Any ideas? Josep, Sebastian?
I have an ngRepeat that populates a list of customers, shown here :
<div ng-repeat="terr in terrData.data">
<div class="customer-row" ng-click="clickCustomerSelect(terr)">
<input class="customer-radio" type="radio" name="customer-select" ng-model="selectedCustomerRow" value="{{terr.customerID}}">
<div class="contact-data-column">{{terr.custNm}}</div>
<div class="primaryphone-data-column">{{terr.primaryPhone}}</div>
<!-- other customer data -->
</div>
</div>
There is a click event on the customer-row div that says if the row is clicked, the radio button for the row should be checked.
The basic controller logic shown here :
$scope.clickCustomerSelect = function(customer){
$scope.selectedCustomerRow = customer.customerID.toString();
//Other business logic
};
I see that whenever the customer row is clicked (not the radio button), the model gets properly updated, and the radio button corresponding to that value is checked. Note that this is expected functionality.
The issue i'm seeing is that if you check the radio button manually (i.e. not clicking the row), the model will no longer respond to updates from clicking the row.
I'm wondering if somehow once you select the radio button you're going outside of angular scope?
EDIT: Sample model
terrData.data = [{
"customerID": 1,
"companyName": "Name 1",
"custNm": "Blank",
"primaryPhone": "111-111-1111"
}, {
"customerID": 2,
"companyName": "Name 2",
"custNm": "Blank",
"primaryPhone": "111-111-1112"
}, {
"customerID": 3,
"companyName": "Name 3",
"primaryPhone": "111-111-1113"
}];
$scope.selectedCustomerRow = customer.customerID.toString();
Replace To:
$scope.selectedCustomerRow = customer.customerID;
onclick with it set selectedCustomerRow.
in HTML
<input class="customer-radio" type="radio" name="customer-select" ng-model="selectedCustomerRow" value="{{terr.customerID}}">
Replace To:
<input class="customer-radio" type="radio" name="customer-select" ng-model="$parent.selectedCustomerRow" value="{{terr.customerID}}">
DEMO
Likely your problem is this: https://stackoverflow.com/a/17607794/170407
Short answer: ng-model almost always needs a dot in it.