Updating View after ng-model change - AngularJS - javascript

How would I go about updating an array that is carrying my ng-model after a button click? I cannot bind them because the data I am selecting from is a list. For the data to update I have to change views or refresh but I would like it to update after I click the button
Here is my HTML and where I would like my ng-model text updated
'<span>HVACs: <ct-input disabled="true" ng-model="data.groupLimits[activeIndex].devices" </ct-input> </span>' + '<br>' +
'<span> Add/Remove Device: <ct-input-list list="hvacsList" ng-model="model" </ct-input-list>' + '</span>' +
+ '<ct-button text="Add Device" show="true" ng-click="addDevice()"> </ct-button>'

If the array is loaded initially from a controller method call, just call that method at the end of whatever you are doing, eg
in controller:
$scope.LoadModel = function(){
myService.loadModel(id).then(function(d){
bindArrayToModel();
})
}
$scope.DoClick=function(){
// something
$scope.LoadModel(); // re-load model here
}
in view:

Related

Angular UI Grid reloading cell templates

I can't figure out how to do what's supposed to be very simple.
I have 10 columns in my UI grid, they are all editable. My objective is dynamically "disable" or have them be "required" inputs, depending on the options of a scope object.
The object:
$scope.columnOptions = {
'column1': 'MANDATORY',
'column2': 'DISABLED'....
}
The cell templates
cellTemplate: '<input ng-disabled="{{ grid.appScope.columnOptions.column1=== \'DISABLED\' }}" ' +
'ng-required="{{ grid.appScope.columnOptions.column1=== \'MANDATORY\' }}" ' +
'data-ng-model="row.entity.column1" style="width:95%">'
This works if the object exists upon initialization.
The problem is that when I change the value of columnOptions, the rows don't get updated.
I have tried different ui-grid APIs to reload my template but it did not work:
$scope.gridApi.core.refresh();
$scope.gridApi.core.raise.reloadData();
$scope.gridApi.core.refreshRows();
$scope.gridApi.core.notifyDataChange('all');
I've added a plunker: http://plnkr.co/edit/3bIrtJuwHNrTeltIPAXw?p=preview
Your cell templates are not correct:
cellTemplate: '<input ng-disabled="grid.appScope.columnOptions.column1=== \'DISABLED\'" ' +
'ng-required="grid.appScope.columnOptions.column1=== \'MANDATORY\' " ' +
'data-ng-model="row.entity.column1" style="width:95%">'
You do not use {{}} within ng- related syntax as it already parses it as angular:
Fixed Plnkr here

How to add a search box inside select element generated by angular-formly

I am trying to add a search box inside select elements. I am using angular-formly library along with angular-formly-material for material design. I am trying to achieve something similar to angular-material select box as shown in pick a vegetable example
ISSUE
I am able to see the search box but I cannot type into that box. Hence filtering does not work. I have no idea where to put some controller code as described in example.
CODE
formlyConfig.setType({
name: 'select',
template: '<md-input-container>'
+'<label for="{{id + \'_\'+ $index}}">'
+' {{to.label}}'
+' </label>'
+ '<md-select ng-model="model[options.key]"'
+ 'md-on-close="clearSearchTerm()"'
+ 'data-md-container-class="selectdemoSelectHeader"'
+ '>'
+'<md-select-header class="demo-select-header">'
+'<input ng-model="searchTerm"'
+'type="search"'
+'placeholder="Search"'
+'class="demo-header-searchbox md-text">'
+'</md-select-header>'
+'<md-optgroup >'
+'<md-option ng-value="option[to.valueProp || \'value\']" ng-repeat="option in to.options |'
+'filter:searchTerm">{{option[to.labelProp || \'name\'] }}</md-option>'
+'</md-optgroup>'
+'</md-select>'
+'</md-input-container>'
});
I found the solution. I was trying to add a controller to fix this but that was not working. To make this work, I used the link option in formly. Here is the working code.
formlyConfig.setType({
name: 'select',
template: '<md-input-container>'
+'<label for="{{id + \'_\'+ $index}}">'
+' {{to.label}}'
+' </label>'
+ '<md-select ng-model="model[options.key]"'
+ 'md-on-close="clearSearchTerm()"'
+ 'data-md-container-class="selectdemoSelectHeader"'
+ '>'
+'<md-select-header class="demo-select-header">'
+'<input ng-model="searchTerm"'
+'type="search"'
+'placeholder="Search"'
+'class="demo-header-searchbox md-text">'
+'</md-select-header>'
+'<md-optgroup >'
+'<md-option ng-value="option[to.valueProp || \'value\']" ng-repeat="option in to.options |'
+'filter:searchTerm">{{option[to.labelProp || \'name\'] }}</md-option>'
+'</md-optgroup>'
+'</md-select>'
+'</md-input-container>'
,
link: function(scope, el, attrs) {
el.find('input').on('keydown', function(ev) {
ev.stopPropagation();
});
}
});
Formly, Angular, Mat-select, Filtering
This answer for users, who still search answer (now the question watched over 1k). It's solution for Material UI. Hope this help someone.
What you need to do:
create custom type (that is really flexible solution)
provide and import it in app.module
don't use <mat-form-field></mat-form-field> wrapper
use ngx-mat-select-search package or your input for searching into select.
More details in my repo.

Telerik Kendo dropdownlist remove item

I have a kendo dropdownlist which options looks like the following:
$scope.addressDropdownOptions = {
dataSource: $scope.customerAddress,
dataTextField: "Address.PrId",
dataValueField: "PrId",
headerTemplate: '<div style="width:100%;">' +
'<span style="padding-left:5px; font-weight:bold;">City</span>' +
'<span style="padding-left:129px; font-weight:bold;">Address</span>' +
'<span style="padding-left:107px; font-weight:bold;">Note</span>' +
'</div>',
valueTemplate: '<span>{{dataItem.Address.City}} </span>' +
'<span>{{dataItem.Address.Street}}</span>',
template: '<div style="width:100%;">' +
'<div class="customerDropDown">{{dataItem.Address.City}}</div>' +
'<div class="customerDropDown">{{dataItem.Address.Street}}</div>' +
'<div class="customerDropDown">{{dataItem.Address.Note}}</div> </div>',
};
The user has the option to select one, and then hit a button, which is supposed to remove the selected item from the dropdownlist.
So I'm doing the following:
$scope.customerAddress.splice(i, 1);
Now the selected item is not an option anymore in the dropdown, BUT - the valueTemplate is still showing the removed item. I'd like that to be the first index of $scope.customerAddress.
Another problem is that the first option in the new list, can not be selected. When I click it, the valueTemplate still results in the previously removed item.
Can anyone help me?
If you remove item directly from the source object (in your case, $scope.customerAddress), the dropDownList won't be aware of that change. If you want to remove an item, it has to be done using the dataSource's remove function:
var ddl = $("#color").data("kendoDropDownList");
var oldData = ddl.dataSource.data();
ddl.dataSource.remove(oldData[0]); //remove first item

Click items in an ng-repeat to fill another list

I have a working plunker where you select a thing from a dropdown and it displays data. I would like to be able to click one of those items and it to fill another list below. with other data. I know of ng-click and thats what I am using currently to just pop up an alert with the data I want to be in the list.
This is the section in question:
<div>
<select ng-options="post as post.id for post in allPosts" ng-model="selectPost" ng-change="select()">
<option value="">--select--</option>
</select>
<input type="text" ng-model="searchText" ng-change="search()" />
<ul>
<li data-ng-repeat="item in records | orderBy:'email':reverse" ng-click="moreInfo(item)">
{{item.email}}
</li>
</ul>
</div>
Ideally I want a list like what is in the popup something like:
Email: 'email...'
Name: 'name...'
Body: 'body...'
Like what is in the popup, but to show up below the list of things displayed from choosing the dropdown. (on my webpage it will be over to the right so I am not concerned about formatting, just how to do it). But I DO NOT want the the list to show up if I don't click on an option.
Plunker here.
edit: I am beginning to think maybe an ng-show will do the trick in some fashion, yet, I still do not know how I would pass the data down to the list.
Create a div that will be visible when a message variable is available.
<div ng-show="message">
{{ message }}
</div>
and in your controller, assign the contents for the moreInfo to a $scope.message:
$scope.moreInfo = function(id) {
$scope.message = "Email: " + id.email + "\nName: " + id.name + "\nBody: " + id.body;
};
Here's an updated plunker.
I edited your plunker , hope that is what you wanted.. and it's better for you to use controller as syntax article and you should looki into styleguide too i like this one by John Papa styleguide
It's actually quite straightforward:
First, set your new text to a scope value on click:
$scope.moreInfo = function(id) {
$scope.curResults = "Email: " + id.email + "\nName: " + id.name + "\nBody: " + id.body
//alert("Email: " + id.email + "\nName: " + id.name + "\nBody: " + id.body);
};
Then, simply assign this value to another div:
<div ng-show="curResults">{{curResults}}</div>
Then, whenever you click on the results, curResults is updated and shown in that div.
ng-show="curResults" makes sure the div is only shown when there's a value set to curResults.

Why is my code looping twice?

I'm making a data visualisation tool where you can input your own data. The data values are stored in an unordered list like this: <ul><li data-name='name'><a href='#' onclick='showEditDv(this);'>Edit</a><span class='name'>name</span><span class='seperator'> | </span><span class='value'>7</span></li></ul. There can be more than one list item in the list. When you click on the Edit button it calls the showEditDv() function, giving a reference to itself. Before I show the function, I will say that the data object is organised like this:
data ->
name: "root",
children: [ {name: "something", size: "7"},
{name: "something-else", size: "999"} ]
This is the code for the function:
function showEditDv(object) {
var name = $(object).parent().attr("data-name"),
input = new Opentip($(object), {removeElementsOnHide: true, target: null, showOn: null, hideTrigger: "closeButton"}),
disabled = (data.children[getChildIndexByName(name)].hasOwnProperty("children")) ? "disabled" : "";
input.setContent("<label>Name:</label><input type='text' data-prevname='" + name + "' value='" + name + "' class='dv-add-name' /><label>Value:</label><input " + disabled + " type='text' class='dv-add-value' value='" + data.children[getChildIndexByName(name)].size + "' /><button class='callEditDv'>Apply</button>"); // Set content of opentip
input.show();
$("body").on("click", ".callEditDv", function() {
var newname = $(this).siblings(".dv-add-name").val(),
prevname = $(this).siblings(".dv-add-name").attr("data-prevname"),
value = $(this).siblings(".dv-add-value").val();
if (newname !== prevname)
{
data.children[ getChildIndexByName(prevname) ].name = newname; // Update name
$(object).parent().attr("data-name", newname); // Update parent data
$(object).siblings(".name").text(newname); // Update form
}
if (data.children[ getChildIndexByName(newname) ].size !== value)
{
data.children[ getChildIndexByName(newname) ].size = value;
$(object).siblings(".value").text(value);
}
input.hide();
});
}
It uses Opentip, which is just a way of creating dynamic popups / tooltips. The problem is that once you have changed a data value once, when you try to change it again it loops through the code twice! The first time everything works as expected, but the second time it does it again, using the same prevname, which means that getChildIndexByName returns undefined and it can't set the variable causing an error. getChildIndexByName loops through the values of data.children checking the names until it finds a match, and then returns the index of the object in the array.
Thanks in advance!
Try this:
$("body").off('click').on("click",...
jQuery Documentations
Event handlers attached with .bind() can be removed with .unbind().
(As of jQuery 1.7, the .on() and .off() methods are preferred to
attach and remove event handlers on elements.)
change:
$("body").on("click",...
to
$("body").unbind('click').on("click",
Hope this help!

Categories